package com.pwt.web.controller;

import com.pwt.Globals;
import com.pwt.StationService;
import com.pwt.common.annotation.Log;
import com.pwt.common.core.controller.BaseController;
import com.pwt.common.core.domain.AjaxResult;
import com.pwt.common.enums.BusinessType;
import com.pwt.netty.ChargerServer;
import com.pwt.netty.MessageSender;
import com.pwt.netty.client.PlcClient;
import com.pwt.netty.common.charger.ChargerException;
import com.pwt.netty.common.charger.ResponseMessage;
import com.pwt.netty.common.charger.client.ClientResponseData;
import com.pwt.netty.common.constants.ExchangeWorkState;
import com.pwt.netty.common.plc.PlcCommand;
import com.pwt.netty.message2.ChargerGun;
import com.pwt.netty.message2.ExchangeWorkMode;
import com.pwt.web.domain.ChangeHolderParam;
import com.pwt.web.domain.ChangeWarehouse;
import com.pwt.web.domain.ChargeParam;
import com.pwt.web.domain.ExchangeWorkModeParam;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.stream.Collectors;

import static com.pwt.Globals.emergencyChargerId;
import static com.pwt.netty.MessageSender.MSG_EXCHANGE_WORK_MODE;

/**
 * @author linyun
 * @version V1.0
 * @Title: OperationController
 * @Description: 站控系统操作类
 * @date 2022/11/21
 **/
@Api
@Slf4j
@RestController
@RequestMapping("/web/operation")
public class PwtOperationController extends BaseController {


    private PlcClient plcClient;

    private ChargerServer chargerServer;

    private StationService stationService;

    @Autowired
    public void setPlcClient(PlcClient plcClient) {
        this.plcClient = plcClient;
    }

    @Autowired
    public void setChargerServer(ChargerServer chargerServer) {
        this.chargerServer = chargerServer;
    }

    @Autowired
    public void setStationService(StationService stationService) {
        this.stationService = stationService;
    }

    @PreAuthorize("@ss.hasPermi('web:operation:changeMode')")
    @Log(title = "换电模式变更", businessType = BusinessType.UPDATE)
    @ApiOperation("换电模式变更")
    @PostMapping("/changeMode")
    public AjaxResult changeMode(@RequestBody ExchangeWorkModeParam param) {
        int mode = param.getMode();
        if (mode < 1 || mode > 2) {
            return AjaxResult.error("参数错误！");
        }
        if (Globals.uiData.getExchangeWorkMode().getValue() == mode) {
            success("当前换电模式已经是" + mode + "，无需变更");
        }


        boolean b = plcClient.sendCommand(PlcCommand.W_SetChargeMode, mode == 2);
        if (b) {
            ExchangeWorkMode exchangeWorkMode = new ExchangeWorkMode();
            exchangeWorkMode.setValue(mode);
            Globals.uiData.setExchangeWorkMode(exchangeWorkMode);
            MessageSender.send(MSG_EXCHANGE_WORK_MODE, exchangeWorkMode);
        }
        return b ? success() : AjaxResult.error("发送模式切换指令失败！");
    }

    @PreAuthorize("@ss.hasPermi('web:operation:reset')")
    @Log(title = "复位", businessType = BusinessType.UPDATE)
    @ApiOperation("复位")
    @PostMapping("/reset")
    public AjaxResult reset() {
        boolean b = plcClient.sendCommand(PlcCommand.W_Reset, true);
        return b ? success() : AjaxResult.error("发送复位指令失败！");
    }

    @PreAuthorize("@ss.hasPermi('web:operation:suspend')")
    @Log(title = "暂停", businessType = BusinessType.UPDATE)
    @ApiOperation("暂停")
    @PostMapping("/suspend")
    public AjaxResult suspend() {
        int remoteEnabled = plcClient.isRemoteEnabled();
        if (remoteEnabled == -1) {
            return AjaxResult.error("发送指令失败！请重试。");
        }
        if (remoteEnabled == 0) {
            return AjaxResult.error("发送指令失败！换电机器人当前禁止远程操作");
        }
        boolean b = plcClient.sendCommand(PlcCommand.W_Pause, true);
        return b ? success() : AjaxResult.error("发送暂停指令失败！");
    }

    @PreAuthorize("@ss.hasPermi('web:operation:continue')")
    @Log(title = "继续", businessType = BusinessType.UPDATE)
    @ApiOperation("继续")
    @PostMapping("/continue")
    public AjaxResult continue1() {
        int remoteEnabled = plcClient.isRemoteEnabled();
        if (remoteEnabled == -1) {
            return AjaxResult.error("发送指令失败！请重试。");
        }
        if (remoteEnabled == 0) {
            return AjaxResult.error("发送指令失败！换电机器人当前禁止远程操作");
        }
        boolean b = plcClient.sendCommand(PlcCommand.W_Resume, true);
        return b ? success() : AjaxResult.error("发送继续指令失败！");
    }

    @PreAuthorize("@ss.hasPermi('web:operation:change')")
    @Log(title = "换仓", businessType = BusinessType.UPDATE)
    @ApiOperation("换仓")
    @PostMapping(value = "/moveBattery")
    public AjaxResult moveBattery(@RequestBody ChangeWarehouse cw) {
        if (cw.getSource() < 1 || cw.getSource() > Globals.ACTUAL_HOLDER_COUNT) {
            return AjaxResult.error("取仓位号不存在！");
        }
        if (cw.getTarget() < 1 || cw.getTarget() > Globals.ACTUAL_HOLDER_COUNT) {
            return AjaxResult.error("放仓位不存在！");
        }
        if (cw.getSource() == cw.getTarget()) {
            return AjaxResult.error("取放仓位不能相同，请重试");
        }
        int remoteEnabled = plcClient.isRemoteEnabled();
        if (remoteEnabled == -1) {
            return AjaxResult.error("发送指令失败！请重试。");
        }
        if (remoteEnabled == 0) {
            return AjaxResult.error("发送指令失败！换电机器人当前禁止远程操作");
        }
        try {
            stationService.moveBattery(cw.getSource(), cw.getTarget(), false);
        } catch (Exception e) {
            return AjaxResult.error("换仓失败：" + e.getMessage());
        }
        return success();
    }

    @Log(title = "设置下一次换电", businessType = BusinessType.UPDATE)
    @ApiOperation("设置下一次换电时取电仓位")
    @PostMapping(value = "/setNextChargingGetBattery")
    public AjaxResult setNextChargingGetBattery(@RequestBody ChangeHolderParam param) {
        if (stationService.getExchangeState() != ExchangeWorkState.IDLE.getValue()) {
            return AjaxResult.error("正在换电中，请在换电前设置取电仓位！");
        }
        int i = Integer.parseInt(param.getHolderId());
        if (i > Globals.ACTUAL_HOLDER_COUNT) {
            return AjaxResult.error("仓位号不存在！");
        }
        stationService.setNextGetHolderIndex(i);
        return success();
    }

    @PreAuthorize("@ss.hasPermi('web:operation:scram')")
    @Log(title = "急停", businessType = BusinessType.UPDATE)
    @ApiOperation("急停")
    @PostMapping("/scram")
    public AjaxResult scram() {
        boolean b = plcClient.sendCommand(PlcCommand.W_EmergencyStop, true);
        return b ? success() : AjaxResult.error("发送急停指令失败！");
    }

    @PreAuthorize("@ss.hasPermi('web:operation:endChange')")
    @Log(title = "结束换电", businessType = BusinessType.UPDATE)
    @ApiOperation("结束换电")
    @PostMapping("/endChange")
    public AjaxResult endChange() {
        stationService.completeExchange();
        return success();
    }


    @PreAuthorize("@ss.hasPermi('web:operation:chargerStart')")
    @Log(title = "充电机启动", businessType = BusinessType.UPDATE)
    @ApiOperation("充电机启动")
    @PostMapping("/chargerStart")
    public AjaxResult startCharge(ChargeParam chargeParam) {
        try {
            if (chargeParam.getChargerId().equals(emergencyChargerId)) {
                ChargerGun chargerGun23 = Globals.uiData.getChargerGuns().stream().filter(e -> e.getId().equals(emergencyChargerId + "3")).collect(Collectors.toList()).get(0);
                ChargerGun chargerGun24 = Globals.uiData.getChargerGuns().stream().filter(e -> e.getId().equals(emergencyChargerId + "4")).collect(Collectors.toList()).get(0);

                if (chargerGun23.getState().getState() == 2 || chargerGun23.getState().getState() == 4) {
                    return AjaxResult.error("充电机目前正在应急充电，无法启用充电机！");
                }
                if (chargerGun24.getState().getState() == 2 || chargerGun24.getState().getState() == 4) {
                    return AjaxResult.error("充电机目前正在应急充电，无法启用充电机！");
                }
            }
            ResponseMessage responseMessage = chargerServer.startCharge(chargeParam.getChargerId(), chargeParam.getChargerGunId(), 0, false);
            ClientResponseData responseData = ((ClientResponseData) responseMessage.getMessageData());
            return AjaxResult.success("resp status:" + responseData.getStatus());
        } catch (IllegalAccessException iae) {
            return AjaxResult.error("启动充电机失败, 参数错误!");
        } catch (ChargerException ce) {
            return AjaxResult.error(ce.getMessage());
        } catch (Exception e) {
            log.error("充电充电机失败: param: {}", chargeParam, e);
            return AjaxResult.error("启动充电机失败, 未知错误!");
        }
    }

    @PreAuthorize("@ss.hasPermi('web:operation:chargerStop')")
    @Log(title = "充电机停止", businessType = BusinessType.UPDATE)
    @ApiOperation("充电机停止")
    @PostMapping("/chargerStop")
    public AjaxResult stopCharge(ChargeParam chargeParam) {
        try {
            ResponseMessage responseMessage = chargerServer.stopCharge(chargeParam.getChargerId(), chargeParam.getChargerGunId(), 0);
            ClientResponseData responseData = ((ClientResponseData) responseMessage.getMessageData());
            return AjaxResult.success("resp status:" + responseData.getStatus());
        } catch (IllegalAccessException iae) {
            return AjaxResult.error("启动充电机失败, 参数错误!");
        } catch (ChargerException ce) {
            return AjaxResult.error(ce.getMessage());
        } catch (Exception e) {
            log.error("充电充电机失败: param: {}", chargeParam, e);
            return AjaxResult.error("启动充电机失败, 未知错误!");
        }
    }
}
