package com.example.iot_controlhost.model.controller.relay;

import com.blankj.utilcode.util.StringUtils;
import com.example.iot_controlhost.base.SetAddress;
import com.example.iot_controlhost.model.controller.Controller;
import com.example.iot_controlhost.utils.MMKVUtil;
import com.example.iot_controlhost.utils.MyUtil;
import com.example.iot_controlhost.utils.global.HardwareSetting;
import com.example.iot_controlhost.utils.global.RoomController;
import com.example.iot_controlhost.utils.global.RoomSensor;
import com.example.iot_controlhost.utils.global.SpinnerList;
import com.example.iot_controlhost.utils.log.MyLog;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import android_serialport_api.SerialPortUtil;

/**
 * @Description 继电器
 * @Author DuanKaiji
 * @CreateTime 2023年10月20日 09:26:45
 */
public class Relay extends Controller implements SetAddress {
    /**
     * 继电器下设备通用设置项名
     * 个性化设置项使用name，通用设置项使用TAG
     */
    public static final String TAG = "继电器";
    /**
     * 设备端口
     */
    public final String PORT = name + "端口";

    /**
     * 设备图标资源Id
     */
    private final String ICON_OPEN = name + "icon_open";
    /**
     * 设备图标资源Id
     */
    private final String ICON_CLOSE = name + "icon_close";

    public Relay(String name) {
        super(name);
    }

    public Relay(String name, int iconOpen, int iconClose) {
        super(name);
        setIconOpen(iconOpen);
        setIconClose(iconClose);
    }

    /**
     * 继电器上设备的开关方法
     * 应用于：各种灯、换气扇、
     *
     * @param state 开/关
     * @return 修改成功与否
     */
    public boolean setPowerSupply(boolean state) {
        if (!isAvailable()) {
            MyLog.controllerError(getName() + "未正确配置但尝试控制");
            return false;
        }
        boolean result = true;
        for (int port : getPorts()) {
            result = setPowerSupply(state, port);
        }
        return result;
    }

    /**
     * 继电器上设备的开关方法
     *
     * @param state 开/关
     * @param port  设备端口
     * @return 操作成功与否
     */
    public boolean setPowerSupply(boolean state, int port) {
        String str = null;
        if (isIntegratedController()) {
            str = HardwareSetting.getCommonAddress() + "01" + String.format("%02X", port) + (state ? "1000" : "0000");
        } else {
            if (getModel().equals(getModels()[0])) {
                //能工RS458控制模式
                str = getAddress() + "0500" + String.format("%02X", port - 1) + (state ? "FF00" : "0000");
            } else if (getModel().equals(getModels()[1])) {
                //中盛0-10V模拟量控制
                str = getAddress() + "0600" + String.format("%02X", 9 + port) + (state ? "2710" : "0000");
            } else if (getModel().equals(getModels()[2])) {
                //BBIT-H-v1.0
                /** 01指令
                 * 格式：  地址  类型  端口号 数据位（高位） 数据位（低位） CRC高位   CRC底位
                 * 举例：  01    01    02      0F           A0         74      BC
                 * 数据位：0-4096    发送时需要以十六进制发送
                 * 返回：执行成功后返回对应数据
                 **/
                str = getAddress() + "01" + String.format("%02X", port) + (state ? "2710" : "0000");
            }
        }
        str = str + getCRC(str);
        boolean result = executeInstructions(str, "第" + port + "端口状态设为:" + state);
        if (result) {
            //操作成功 修改状态
            powerSupply = state;
        }
        return result;
    }
    public SerialPortUtil getSerialPortUtil() {
        return serialPortUtil;
    }

    /**
     * 这个方法已重写
     * 因为继电器下的设备用的地址都是Relay的地址，而非各自的地址
     */
    @Override
    public void setAddress(String address) {
        MMKVUtil.put(TAG + "地址", address);
    }

    /**
     * 这个方法已重写
     * 因为继电器下的设备用的地址都是Relay的地址，而非各自的地址
     */
    @Override
    public String getAddress() {
        return MMKVUtil.get(TAG + "地址", SpinnerList.ADDRESS[0]);
    }

    public String getModel() {
        return MMKVUtil.get(TAG + "型号", getModels()[0]);
    }

    public void setModel(String model) {
        MMKVUtil.put(TAG + "型号", model);
    }

    public boolean isEnable() {
        return MMKVUtil.get(TAG + "启用", false);
    }

    public void setEnable(boolean enable) {
        MMKVUtil.put(TAG + "启用", enable);
    }

    public List<Integer> getPorts() {
        String json = MMKVUtil.get(PORT, "[]");
        List<Integer> temp = new Gson().fromJson(json, new TypeToken<List<Integer>>() {
        }.getType());
        return temp;
    }

    public int getIconOpen() {
        return MMKVUtil.get(ICON_OPEN, 0);
    }

    public void setIconOpen(int icon) {
        MMKVUtil.put(ICON_OPEN, icon);
    }

    public int getIconClose() {
        return MMKVUtil.get(ICON_CLOSE, 0);
    }

    public void setIconClose(int icon) {
        MMKVUtil.put(ICON_CLOSE, icon);
    }

    public void addPort(Integer port) {
        String json = MMKVUtil.get(PORT, "[]");
        List<Integer> temp = new Gson().fromJson(json, new TypeToken<List<Integer>>() {
        }.getType());
        temp.add(port);
        MMKVUtil.put(PORT, new Gson().toJson(temp));
    }

    public void removePort(Integer port) {
        String json = MMKVUtil.get(PORT, "[]");
        List<Integer> temp = new Gson().fromJson(json, new TypeToken<List<Integer>>() {
        }.getType());
        temp.remove(port);
        MMKVUtil.put(PORT, new Gson().toJson(temp));
    }

    public void clearAndSetPort(Integer port) {
        List<Integer> temp = new ArrayList<>();
        temp.add(port);
        MMKVUtil.put(PORT, new Gson().toJson(temp));
    }

    public void clearAllPort() {
        List<Integer> temp = new ArrayList<>();
        MMKVUtil.put(PORT, new Gson().toJson(temp));
    }

    /**
     * 继电器设备需要额外判断
     *
     * @return 可用与否
     */
    @Override
    public boolean isAvailable() {
        // 1.是否启用继电器
        boolean b1 = isEnable();
        // 2.是否配置了继电器地址
        boolean b2 = !StringUtils.isEmpty(getAddress());
        // 3.为继电器下的设备且配置了端口
        boolean b3 = PORT.equals(TAG + "端口") || getPorts().size() != 0;
        return b1 && b2 && b3;
    }

    @Override
    public String[] getModels() {
        return new String[]{"MODBUS LH-08", "中盛0-10V模拟量控制", "BBIT-H-v1.0"};
    }
    //____________________________________________________以下为BBIT-H-v1.0继电器特有功能：读取每个继电器每个端口的能耗数据____________________________________
    /**
     * 电压
     */
    private double voltage;
    /**
     * 电流
     */
    private double current;
    /**
     * 实时功率
     */
    private double power;
    /**
     * 能耗
     */
    private double energyConsumption;

    /**
     * 输出能耗传感器数据
     */
    public String getSensorData() {
        return "电压：" + getVoltage() + "V\t\t\t\t电流：" + getCurrent() + "A\n功率：" + getPower() + "W\t\t\t\t总能耗：" + getEnergyConsumption() + "kw·h";
    }

    /**
     * 更新能耗
     */
    public boolean collectSensorData() {
        double tempVoltage = 0;
        double tempCurrent = 0;
        double tempPower = 0;
        double tempConsumption = 0;
        for (int port : getPorts()) {
            String str = RoomController.relay.getAddress() + "02" + String.format("%02X", port) + "0006";
            str = str + getCRC(str);
            String data = RoomController.relay.getSerialPortUtil().sendAndReceiveSerialData(RoomSensor.consumptionSensor, str);
            if (StringUtils.isEmpty(data)) {
                initData();
                return false;
            }
            data = data.substring(2);
            //开始解析
            try {
                String[] PowerArr = substring(data, 2);
                if (PowerArr.length < 19) {
                    initData();
                    return false;
                }
                long V_int = Long.parseLong(PowerArr[3] + PowerArr[4] + PowerArr[5] + PowerArr[6], 16);
                long A_int = Long.parseLong(PowerArr[7] + PowerArr[8] + PowerArr[9] + PowerArr[10], 16);
                long P_int = Long.parseLong(PowerArr[11] + PowerArr[12] + PowerArr[13] + PowerArr[14], 16);
                long PCount_int = Long.parseLong(PowerArr[15] + PowerArr[16] + PowerArr[17] + PowerArr[18], 16);
                double factor = 0.0001;
                DecimalFormat df = new DecimalFormat("#.00");
                tempVoltage += Double.parseDouble(df.format(V_int * factor));
                tempCurrent += Double.parseDouble(df.format(A_int * factor));
                tempPower += Double.parseDouble(df.format(P_int * factor));
                tempConsumption += Double.parseDouble(df.format(PCount_int * factor));
            } catch (Exception e) {
                e.printStackTrace();
                initData();
                return false;
            }
        }
        this.voltage = tempVoltage;
        this.current = tempCurrent;
        this.power = tempPower;
        this.energyConsumption = tempConsumption;
        return true;
    }

    /**
     * 解析失败
     * 后的处理
     */
    private void initData() {
        this.voltage = 0.0;
        this.current = 0.0;
        this.power = 0.0;
        this.energyConsumption = 0.0;
    }
    public double getVoltage() {
        return voltage;
    }

    public void setVoltage(double voltage) {
        this.voltage = voltage;
    }

    public double getCurrent() {
        return current;
    }

    public void setCurrent(double current) {
        this.current = current;
    }

    public double getPower() {
        return power;
    }

    public String getPowerText() {
        // 使用访问器以支持 Fan 等聚合继电器重写功率计算逻辑。
        return new DecimalFormat("0.##").format(getPower());
    }

    public void setPower(double power) {
        this.power = power;
    }

    public double getEnergyConsumption() {
        return energyConsumption;
    }

    public void setEnergyConsumption(double energyConsumption) {
        this.energyConsumption = energyConsumption;
    }

    boolean temp;

    @Override
    public boolean setAddressToNewAddress(String model, String oldAddress, String oldBaud, String newAddress) {
        boolean result = false;
        if (model.equals(getModels()[1])) {
            String editAddress = oldAddress + "06003200" + newAddress;
            editAddress = editAddress + getCRC(editAddress);
            result = editAddress.equals(serialPortUtil.sendAndReceiveSerialData(this, editAddress));
        }
        return result;
    }

    @Override
    public boolean setBaudToNewBaud(String model, String oldAddress, String newBaud) {
        boolean result = true;
        if (model.equals(getModels()[1])) {
            switch (newBaud) {
                case "4800":
                    newBaud = "00";
                    break;
                case "9600":
                    newBaud = "01";
                    break;
                case "14400":
                    newBaud = "02";
                    break;
                case "19200":
                    newBaud = "03";
                    break;
                case "38400":
                    newBaud = "04";
                    break;
                case "56000":
                    newBaud = "05";
                    break;
                case "57600":
                    newBaud = "06";
                    break;
                case "115200":
                    newBaud = "07";
                    break;
                default:
                    return false;
            }
            String editBaud = oldAddress + "06003300" + newBaud;
            editBaud = editBaud + getCRC(editBaud);
            result = editBaud.equals(serialPortUtil.sendAndReceiveSerialData(this, editBaud));
        }
        return result;
    }

    @Override
    public boolean test(String deviceModel, String deviceAddress) {
        if (deviceModel.equals(getModels()[1])) {
            String str = deviceAddress + "06000A" + (!temp ? "2710" : "0000");
            str = str + getCRC(str);
            temp = !temp;
            return executeInstructions(str, "第1端口状态设为:" + temp);
        }
        return false;
    }

    @Override
    public String getTestState() {
        return "继电器1号端口" + (temp ? "已开启" : "已关闭");
    }

}
