package com.example.iot_controlhost.model.sensor;

import com.blankj.utilcode.util.StringUtils;
import com.example.iot_controlhost.model.EnergyRecord;
import com.example.iot_controlhost.utils.MMKVUtil;
import com.example.iot_controlhost.utils.MyUtil;
import com.example.iot_controlhost.utils.database.EnergyDBManager;
import com.example.iot_controlhost.utils.database.SilkwormDBManager;
import com.example.iot_controlhost.utils.global.RoomController;
import com.example.iot_controlhost.utils.global.RxTag;
import com.example.iot_controlhost.utils.global.Variable;
import com.example.iot_controlhost.utils.log.MyLog;

import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;

import android_serialport_api.SerialPortUtil;

/**
 * 能耗传感器
 */
public class ConsumptionSensor extends Sensor {

    /**
     * 电压
     */
    private double voltage;
    /**
     * 电流
     */
    private double current;
    /**
     * 实时功率
     */
    private double power;
    /**
     * 能耗
     */
    private double energyConsumption;

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

    @Override
    public boolean collectSensorData(String model, String address) {
        String str;
        String data = null;
        try {
            if (model.equals(getModels()[1])) {
                //三相IM3332
                // 总能耗
                str = address + "0300000002";
                str = str + getCRC(str);
                data = serialPortUtil.sendAndReceiveSerialData(this, str);
                if (StringUtils.isEmpty(data)) {
                    initData();
                    return false;
                }
                String[] s = substring(data, 2);
                this.energyConsumption = Math.round(Long.parseLong(s[3] + s[4] + s[5] + s[6], 16) * 0.01 * 100.0) / 100.0;
                // 总功率
                str = address + "0320000002";
                str = str + getCRC(str);
                data = serialPortUtil.sendAndReceiveSerialData(this, str);
                if (StringUtils.isEmpty(data)) {
                    initData();
                    return false;
                }
                s = substring(data, 2);
                long pRaw = Long.parseLong(s[3] + s[4] + s[5] + s[6], 16);
                // 功率（假设为32位有符号整数）
                if (pRaw > 0x7FFFFFFF) { // 处理负值
                    pRaw -= 0x100000000L; // 32位有符号整数的负数处理
                }
                this.power = Math.abs(Math.round(pRaw * 0.1 * 100.0) / 100.0);
                // 电流 电压
                str = address + "03203A0009";
                str = str + getCRC(str);
                data = serialPortUtil.sendAndReceiveSerialData(this, str);
                if (StringUtils.isEmpty(data)) {
                    initData();
                    return false;
                }
                double[] UA = getUA(substring(data, 2));
                this.voltage = Math.round(UA[0] * 100.0) / 100.0;
                this.current = Math.round(UA[1] * 100.0) / 100.0;
            } else {
                if (RoomController.relay.getModel().equals(RoomController.relay.getModels()[2])) {
                    //判断是否为 BBIT-H-v1.0型继电器 需要使用控制器的串口工具进行通信
                    str = RoomController.relay.getAddress() + "02090006";
                    str = str + getCRC(str);
                    data = RoomController.relay.getSerialPortUtil().sendAndReceiveSerialData(this, str);
                } else if (model.equals(getModels()[0])) {
                    //IM1281B
                    str = address + "0300480004";
                    str = str + getCRC(str);
                    data = serialPortUtil.sendAndReceiveSerialData(this, str);
                }
                if (StringUtils.isEmpty(data)) {
                    initData();
                    return false;
                } else if (RoomController.relay.getModel().equals(RoomController.relay.getModels()[2])) {
                    data = data.substring(2);
                }
                //开始解析
                String[] PowerArr = substring(data, 2);
                if (PowerArr.length < 19) {
                    initData();
                    return false;
                }
                long v = Long.parseLong(PowerArr[3] + PowerArr[4] + PowerArr[5] + PowerArr[6], 16);
                long a = Long.parseLong(PowerArr[7] + PowerArr[8] + PowerArr[9] + PowerArr[10], 16);
                long p = Long.parseLong(PowerArr[11] + PowerArr[12] + PowerArr[13] + PowerArr[14], 16);
                long c = Long.parseLong(PowerArr[15] + PowerArr[16] + PowerArr[17] + PowerArr[18], 16);
                double factor = 0.0001;
                DecimalFormat df = new DecimalFormat("#.00");
                this.voltage = Double.parseDouble(df.format(v * factor));
                this.current = Double.parseDouble(df.format(a * factor));
                this.power = Double.parseDouble(df.format(p * factor));
                this.energyConsumption = Double.parseDouble(df.format(c * factor));
            }
//                MyLog.sensor("电压：" + this.voltage);
//                MyLog.sensor("电流：" + this.current);
//                MyLog.sensor("功率：" + this.power);
//                MyLog.sensor("总能耗：" + this.energyConsumption);
            if (System.currentTimeMillis() - getLastRecordTime() > Variable.SENSOR_RECORD_TIME && this.energyConsumption > 0.0) {
                EnergyDBManager.insert(new EnergyRecord(null, this.energyConsumption, new Date()));
                setLastRecordTime(System.currentTimeMillis());
            }
        } catch (Exception e) {
            initData();
            e.printStackTrace();
            return false;
        }
        return true;
    }

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

    @Override
    public boolean isEnable() {
        if (RoomController.relay.getModels()[2].equals(RoomController.relay.getModel())) {
            //BBIT-H-v1.0 则默认功耗传感器开启 (BBIT-H有其自己的功耗计算方法)
            return true;
        }
        return super.isEnable();
    }

    @Override
    public String toString() {
        return "电压：" + getVoltage() + "V\t\t电流：" + getCurrent() + "A\t\t功率：" + getPower() + "W";
//        + "\n今日能耗：" + getTodayEnergyConsumption() + "kw·h\t\t总能耗：" + getEnergyConsumption() + "kw·h"
    }

    /**
     * 获取总能耗
     */
    public double getEnergyConsumption() {
        return energyConsumption;
    }

    private double[] getUA(String[] data) {
        double[] result = new double[3];
        try {
            // 电压
            long ua = Long.parseLong(data[3] + data[4], 16);
            long ub = Long.parseLong(data[9] + data[10], 16);
            long uc = Long.parseLong(data[15] + data[16], 16);
            // 电流
            long aa = Long.parseLong(data[5] + data[6] + data[7] + data[8], 16);
            long ab = Long.parseLong(data[11] + data[12] + data[13] + data[14], 16);
            long ac = Long.parseLong(data[17] + data[18] + data[19] + data[20], 16);

            result[0] = 0.1 * (ua + ub + uc) / 3;
            result[1] = 0.001 * (aa + ab + ac);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 获取本蚕季能耗
     */
    public double getSeasonEnergyConsumption() {
        long startTimestamp;
        if (SilkwormDBManager.isStarting()) {
            startTimestamp = SilkwormDBManager.getLatestSilkworm().getStartDate().getTime();
        } else {
            // 不在共育期间时 取最近15天、最近启动、最近结束共育后三者间最新的时间作为开始时间开始计算
            // 获取15天前的时间戳
            long fifteenDaysAgoTimestamp = System.currentTimeMillis() - 15L * 24 * 60 * 60 * 1000;
            // 取上次长时间未启动后启动的时间
            long lastLongTimeNotStart = MMKVUtil.get(RxTag.IS_LONG_TIME_NOT_START, -1l);
            // 取最新的作为开始时间
            startTimestamp = Math.max(lastLongTimeNotStart, fifteenDaysAgoTimestamp);
            // 获取上次共育结束时的时间戳
            if (SilkwormDBManager.getLatestSilkworm().getEndDate() != null) {
                // 如果有上次共育结束时间，则取上次共育结束时间
                startTimestamp = Math.max(startTimestamp, SilkwormDBManager.getLatestSilkworm().getEndDate().getTime());
            }
        }
        return getStartToEndConsumption(startTimestamp, getTodayEndTimestamp());
    }

    /**
     * 获取当日能耗
     */
    public double getTodayEnergyConsumption() {
        return getStartToEndConsumption(getTodayStartTimestamp(), getTodayEndTimestamp());
    }

    /**
     * 获取从开始到结束时间的能耗
     */
    private double getStartToEndConsumption(long startDate, long endDate) {
        double result = EnergyDBManager.queryDateRange(startDate, endDate);
        // 格式化结果，保留两位小数
        String formattedResult = new DecimalFormat("#.##").format(result);
        return Double.parseDouble(formattedResult);
    }

    /**
     * 获取今天的开始时间戳（零时零分零秒）
     */
    private long getTodayStartTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获取今天的结束时间戳（23时59分59秒）
     */
    private long getTodayEndTimestamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTimeInMillis();
    }

    @Override
    public String[] getModels() {
        return new String[]{"IM1281B", "三相IM3332"};
    }


    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 void setPower(double power) {
        this.power = power;
    }

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

    @Override
    public boolean setAddressToNewAddress(String model, String oldAddress, String oldBaud, String newAddress) {
        if (model.equals(getModels()[0])) {
            // (3：1200bps 4：2400bps)
            // (5：4800bps 6：9600bps)
            // (7：19200bps）
            switch (oldBaud) {
                case "1200":
                    oldBaud = "03";
                    break;
                case "2400":
                    oldBaud = "04";
                    break;
                case "4800":
                    oldBaud = "05";
                    break;
                case "9600":
                    oldBaud = "06";
                    break;
                case "19200":
                    oldBaud = "07";
                    break;
                default:
                    return false;
            }
            //修改地址指令
            String edit = oldAddress + "100004000102" + newAddress + oldBaud;
            edit = edit + getCRC(edit);
            serialPortUtil.sendAndReceiveSerialData(this, edit);
            System.out.println(SerialPortUtil.R);
            //如果修改成功，返回的数据为：新地址+1000040001+校验码
            String success = newAddress + "1000040001";
            success = success + getCRC(success);
            return success.equals(SerialPortUtil.R.substring(8));
        } else {
            //三相IM3332
            //修改地址指令
            String edit = oldAddress + "10400000010200" + newAddress;
            edit = edit + getCRC(edit);
            String re = serialPortUtil.sendAndReceiveSerialData(this, edit);
            //如果修改成功，返回的数据为：新地址+1000040001+校验码
            String success = oldAddress + "1040000001";
            success = success + getCRC(success);
            return success.equals(re);
        }
    }

    @Override
    public boolean setBaudToNewBaud(String model, String oldAddress, String newBaud) {
        if (model.equals(getModels()[0])) {
            // (3：1200bps 4：2400bps)
            // (5：4800bps 6：9600bps)
            // (7：19200bps）
            switch (newBaud) {
                case "1200":
                    newBaud = "03";
                    break;
                case "2400":
                    newBaud = "04";
                    break;
                case "4800":
                    newBaud = "05";
                    break;
                case "9600":
                    newBaud = "06";
                    break;
                case "19200":
                    newBaud = "07";
                    break;
                default:
                    return false;
            }
            //修改地址指令
            String edit = oldAddress + "100004000102" + oldAddress + newBaud;
            edit = edit + getCRC(edit);
            serialPortUtil.sendAndReceiveSerialData(this, edit);
            //如果修改成功，返回的数据为：新地址+1000040001+校验码
            String success = oldAddress + "1000040001";
            success = success + getCRC(success);
            return success.equals(SerialPortUtil.R.substring(2));
        } else {
            // 三相IM3332
//            0x02表示600，0x04表示1200，0x08表示2400，
//            0x10表示4800，0x20表示9600，0x40表示19200
            String baud = "00";
            switch (newBaud) {
                case "600":
                    baud = "02";
                    break;
                case "1200":
                    baud = "04";
                    break;
                case "2400":
                    baud = "08";
                    break;
                case "4800":
                    baud = "10";
                    break;
                case "9600":
                    baud = "20";
                    break;
                case "19200":
                    baud = "40";
                    break;
                default:
                    return false;
            }
            //修改波特率指令
            String edit = oldAddress + "10400400010200" + baud;
            edit = edit + getCRC(edit);
            String re = serialPortUtil.sendAndReceiveSerialData(this, edit);
            //如果修改成功，返回的数据为：新地址+1000040001+校验码
            String success = oldAddress + "1040040001";
            success = success + getCRC(success);
            MyLog.sensor("修改波特率success：" + success + "\nR:" + SerialPortUtil.R);
            return success.equals(re);
        }
    }

}
