"""
Implementation for SMA Speedwire

Originally based on https://github.com/Wired-Square/sma-query/blob/main/src/sma_query_sw/commands.py
Improved with Information from https://github.com/mhop/fhem-mirror/blob/master/fhem/FHEM/76_SMAInverter.pm
Receiver classes completely reimplemented by little.yoda

"""

from .const import Identifier
from .sensor import Sensor
from .const import SMATagList
from typing import Any, Dict, Optional, List, Annotated
import dataclasses_struct as dcs

responseDef = {
    "00464B01": [],  # Netzspannung Phase L1 gegen L2
    "00464C01": [],  # Netzspannung Phase L2 gegen L3
    "00464D01": [],  # Netzspannung Phase L3 gegen L1
    "00416601": [],  # WaitingTimeUntilFeedIn  WaitingTimeUntilFeedIn
    "00411E01": [],  # MaxACPower
    "00411F01": [],  # MaxACPower
    "00412001": [],  # MaxACPower
    "00462E01": [],  # OperationTime
    "00462F01": [],  # OperationTime
    "00823401": [
        {
            "cmd": "Firmware",
            "format": "version",
            "sensor": Sensor("Firmware", Identifier.device_sw_version),
            "idx": 4,
        }
    ],
    "00260101": [
        {
            "cmd": "EnergyProduction",
            "format": "uint",
            "sensor": Sensor("total", Identifier.total_yield, factor=1000, unit="kWh"),
            "idx": 0,
        }
    ],
    "40251E01": [
        {
            "cmd": "SpotDCPower",
            "format": "uint",
            "sensor": Sensor(
                "spot_dc_power1", Identifier.pv_power_a, factor=1, unit="W"
            ),
            "idx": 0,
        }
    ],
    "40251E02": [
        {
            "cmd": "SpotDCPower",
            "format": "uint",
            "sensor": Sensor(
                "spot_dc_power2", Identifier.pv_power_b, factor=1, unit="W"
            ),
            "idx": 0,
        }
    ],
    "40251E03": [
        {
            "cmd": "SpotDCPower",
            "format": "uint",
            "sensor": Sensor(
                "spot_dc_power3", Identifier.pv_power_c, factor=1, unit="W"
            ),
            "idx": 0,
        }
    ],
    "40464001": [
        {
            "cmd": "spot_ac_power",
            "format": "uint",
            "sensor": Sensor("spot_ac_power1", Identifier.power_l1, factor=1, unit="W"),
            "idx": 0,
        }
    ],
    "40464101": [
        {
            "cmd": "spot_ac_power",
            "format": "uint",
            "sensor": Sensor("spot_ac_power2", Identifier.power_l2, factor=1, unit="W"),
            "idx": 0,
        }
    ],
    "40464201": [
        {
            "cmd": "spot_ac_power",
            "format": "uint",
            "sensor": Sensor("spot_ac_power3", Identifier.power_l3, factor=1, unit="W"),
            "idx": 0,
        }
    ],
    "08412801": [
        {
            "cmd": "OperatingStatus",
            "format": "uint",
            "sensor": [
                Sensor(
                    "GeneralOperatingStatus",
                    Identifier.operating_status_genereal,
                    factor=1,
                    mapper=SMATagList,
                ),
                Sensor(
                    "GeneralOperatingStatus2",
                    "Temp GeneralOperatingStatus2",
                    factor=1,
                    mapper=SMATagList,
                ),
            ],
            "mask": 0x00FFFFFF,
            "idx": 0,
        }
    ],
    "0046C201": [
        {
            "cmd": "SpotDCPower_3",
            "format": "uint",
            "sensor": Sensor("pv_power", Identifier.pv_power, unit="W"),
            "idx": 0,
        }
    ],
    "40263F01": [
        {
            "cmd": "SpotACTotalPower",
            "format": "uint",
            "sensor": Sensor("grid_power", Identifier.grid_power, unit="W"),
            "idx": 0,
        }
    ],
    "00464801": [
        {
            "cmd": "spot_ac_voltage",
            "format": "uint",
            "sensor": Sensor(
                "spot_ac_voltage1", Identifier.voltage_l1, factor=100, unit="V"
            ),
            "idx": 0,
        }
    ],
    "00464901": [
        {
            "cmd": "spot_ac_voltage",
            "format": "uint",
            "sensor": Sensor(
                "ac_voltage_l1", Identifier.voltage_l2, factor=100, unit="V"
            ),
            "idx": 0,
        }
    ],
    "00464A01": [
        {
            "cmd": "spot_ac_voltage",
            "format": "uint",
            "sensor": Sensor(
                "ac_voltage_l2", Identifier.voltage_l3, factor=100, unit="V"
            ),
            "idx": 0,
        }
    ],
    "40465301": [
        {
            "cmd": "spot_ac_voltage",
            "format": "uint",
            "sensor": Sensor(
                "ac_current_l1", Identifier.current_l1, factor=1000, unit="A"
            ),
            "idx": 0,
        }
    ],
    "40465401": [
        {
            "cmd": "spot_ac_voltage",
            "format": "uint",
            "sensor": Sensor(
                "ac_current_l2", Identifier.current_l2, factor=1000, unit="A"
            ),
            "idx": 0,
        }
    ],
    "40465501": [
        {
            "cmd": "spot_ac_voltage",
            "format": "uint",
            "sensor": Sensor(
                "ac_current_l3", Identifier.current_l3, factor=1000, unit="A"
            ),
            "idx": 0,
        }
    ],
    "08412B01": [
        {
            "cmd": "OperatingStatus",
            "format": "uint",
            "mask": 0x00FFFFFF,
            "sensor": Sensor(
                "OperatingStatus", Identifier.operating_status, mapper=SMATagList
            ),
            "idx": 0,
        }
    ],
    "0046C301": [
        {
            "cmd": "PVEnergyProduction",
            "format": "uint",
            "sensor": Sensor(
                "pvEnergyProduction", Identifier.pv_gen_meter, unit="kWh", factor=1000
            ),
            "idx": 0,
        }
    ],
    "0846A601": [
        {
            "cmd": "GridConection",
            "mask": 0x00FFFFFF,
            "format": "uint",
            #                "sensor": , TODO
            "idx": 0,
        }
    ],
    "08214801": [
        {
            "cmd": "DeviceStatus",
            "format": "uint",
            "mask": 0x00FFFFFF,
            "sensor": Sensor("inverter_status", Identifier.status, mapper=SMATagList),
            "idx": 0,
        }
    ],
    "40451F01": [
        {
            "cmd": "SpotACCurrent",
            "format": "uint",
            "sensor": Sensor(
                "spot_dc_voltage1", Identifier.pv_voltage_a, factor=100, unit="V"
            ),
            "idx": 0,
        }
    ],
    "40451F02": [
        {
            "cmd": "SpotACCurrent",
            "format": "uint",
            "sensor": Sensor(
                "spot_dc_voltage2", Identifier.pv_voltage_b, factor=100, unit="V"
            ),
            "idx": 0,
        }
    ],
    "40451F03": [
        {
            "cmd": "SpotACCurrent",
            "format": "uint",
            "sensor": Sensor(
                "spot_dc_voltage3", Identifier.pv_voltage_c, factor=100, unit="V"
            ),
            "idx": 0,
        }
    ],
    "40452101": [
        {
            "cmd": "SpotACCurrent",
            "format": "uint",
            "sensor": Sensor(
                "spot_dc_current1", Identifier.pv_current_a, factor=1000, unit="A"
            ),
            "idx": 0,
        }
    ],
    "40452102": [
        {
            "cmd": "SpotACCurrent",
            "format": "uint",
            "sensor": Sensor(
                "spot_dc_current2", Identifier.pv_current_b, factor=1000, unit="A"
            ),
            "idx": 0,
        }
    ],
    "40452103": [
        {
            "cmd": "SpotACCurrent",
            "format": "uint",
            "sensor": Sensor(
                "spot_dc_current3", Identifier.pv_current_c, factor=1000, unit="A"
            ),
            "idx": 0,
        }
    ],
    "08416401": [
        {
            "cmd": "GridRelayStatus",
            "format": "uint",
            "mask": 0x00FFFFFF,
            "sensor": Sensor(
                "GridRelayStatus", Identifier.grid_relay_status, mapper=SMATagList
            ),
            "idx": 0,
        }
    ],
    "00465701": [
        {
            "cmd": "SpotGridFrequency",
            "format": "uint",
            "sensor": Sensor(
                "grid_frequency", Identifier.frequency, factor=100, unit="Hz"
            ),
            "idx": 0,
        }
    ],
    "10821E01": [
        {
            "cmd": "TypeLabel",
            "format": "uint",
            # "sensor": TODO Vermutlich String
            "idx": 0,
        }
    ],
    "08821F01": [
        {
            "cmd": "TypeLabel",
            "format": "uint",
            "mask": 0x00FFFFFF,
            "sensor": Sensor(
                "inverter_class", Identifier.device_class, mapper=SMATagList
            ),
            "idx": 0,
        }
    ],
    "08822001": [
        {
            "cmd": "TypeLabel",
            "format": "uint",
            "mask": 0x00FFFFFF,
            "sensor": Sensor(
                "inverter_type", Identifier.device_type, mapper=SMATagList
            ),
            "idx": 0,
        }
    ],
    "00262201": [
        {
            "cmd": "energy_production",
            "format": "uint",
            "sensor": Sensor("today", Identifier.daily_yield, unit="Wh"),
            "idx": 0,
        }
    ],
    "00254F01": [
        {
            "cmd": "",
            "format": "uint",
            "sensor": Sensor(
                "Insulation_2",
                Identifier.pv_isolation_resistance,
                unit="kOhm",
                factor=1000,
            ),
            "idx": 0,
        }
    ],
    "40254E01": [
        {
            "cmd": "",
            "format": "uint",
            "sensor": Sensor(
                "Insulation_1",
                Identifier.insulation_residual_current,
                unit="mA",
            ),
            "idx": 0,
        }
    ],
    "00462401": [
        {
            "cmd": "EM_1",
            "format": "uint",
            "sensor": Sensor(
                "meter_yield",
                Identifier.metering_total_yield,
                unit="kWh",
                factor=1000,
            ),
            "idx": 0,
        }
    ],
    "40237701": [
        {
            "cmd": "InverterTemperature",
            "format": "uint",
            "sensor": Sensor(
                "InverterTemperature",
                Identifier.temp_a,
                unit="°C",
                factor=100,
            ),
            "idx": 0,
        }
    ],
    "00295A01": [
        {
            "cmd": "ChargeStatus",
            "format": "uint",
            "sensor": Sensor("ChargeStatus", Identifier.battery_soc_total, unit="%"),
            "idx": 0,
        }
    ],
    "40491E01": [
        {
            "cmd": "BatteryInfo",
            "format": "uint",
            "sensor": Sensor("TEMP BAT_CYCLES", "TEMP Battery Cycles"),
            "idx": 0,
        }
    ],
    "40495B01": [
        {
            "cmd": "batteryTemp",
            "format": "uint",
            "sensor": Sensor(
                "batteryTemp",
                Identifier.battery_temp_a,
                unit="°C",
                factor=10,
            ),
            "idx": 0,
        }
    ],
    "00496701": [
        {
            "cmd": "SpotBatteryLoad",
            "format": "uint",
            "sensor": Sensor(
                "SpotBatteryLoad",
                Identifier.battery_charge_total,
                unit="kWh",
                factor=1000,
            ),
            "idx": 0,
        }
    ],
    "00496801": [
        {
            "cmd": "SpotBatteryUnload",
            "format": "uint",
            "sensor": Sensor(
                "SpotBatteryUnLoad",
                Identifier.battery_discharge_total,
                unit="kWh",
                factor=1000,
            ),
            "idx": 0,
        }
    ],
    "00495C01": [
        {
            "cmd": "battery_voltage_a",
            "format": "uint",
            "sensor": Sensor(
                "battery_voltage_a",
                Identifier.battery_voltage_a,
                unit="V",
                factor=100,
            ),
            "idx": 0,
        }
    ],
    "40495D01": [
        {
            "cmd": "battery_current_a",
            "format": "uint",
            "sensor": Sensor(
                "battery_current_a",
                Identifier.battery_current_a,
                unit="A",
                factor=1000,
            ),
            "idx": 0,
        }
    ],
    "00696E01": [
        {
            "cmd": "BatteryInfo_Capacity",
            "format": "uint",
            "sensor": Sensor(
                "BatteryInfo_Capacity", Identifier.battery_capacity_total, unit="%"
            ),
            "idx": 0,
        }
    ],
    "00496901": [
        {
            "cmd": "BatteryInfo_Charge",
            "format": "uint",
            "sensor": Sensor(
                "BatteryInfo_Charge", Identifier.battery_power_charge_total, unit="W"
            ),
            "idx": 0,
        }
    ],
    "00496A01": [
        {
            "cmd": "BatteryInfo_Charge",
            "format": "uint",
            "sensor": Sensor(
                "BatteryInfo_DisCharge",
                Identifier.battery_power_discharge_total,
                unit="W",
            ),
            "idx": 0,
        }
    ],
    "00462501": [
        {
            "cmd": "EM_1",
            "format": "uint",
            "sensor": Sensor(
                "EM1_1 Identifier.metering_total_absorbed",
                Identifier.metering_total_absorbed,
                unit="kWh",
                factor=1000,
            ),
            "idx": 0,
        }
    ],
    "40463601": [
        {
            "cmd": "EM_3",
            "format": "uint",
            "sensor": Sensor(
                "EM3 Identifier.metering_power_supplied",
                Identifier.metering_power_supplied,
                unit="W",
            ),
            "idx": 0,
        }
    ],
    "40463701": [
        {
            "cmd": "EM_3",
            "format": "uint",
            "sensor": Sensor(
                "EM3 Identifier.metering_power_absorbed",
                Identifier.metering_power_absorbed,
                unit="W",
            ),
            "idx": 0,
        }
    ],
    "00893701": [
        {
            "cmd": "BatteryInfo_4",
            "format": "uint",
            "sensor": Sensor(
                "EM3 BatteryInfo_4", "TEMP battery_capacity_rated", unit="Wh"
            ),
            "idx": 4,
        }
    ],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
    # "": [{
    #             "cmd": "",
    #             "format": "uint",
    #             "sensor": ,
    #             "idx": 0
    # }],
}

commands = {
    "login": {
        "command": 0xFFFD040C,
        "response": 0xFFFD040D,
        "first": 0x0030CB00,
        "last": 0x0030CB00,
    },
    "logoff": {"command": 0xFFFD010E, "response": 0xFFFD010F},
    "TypeLabel": {
        "command": 0x58000200,
        "first": 0x00821E00,
        "last": 0x008220FF,
    },
    "EnergyProduction": {
        "command": 0x54000200,
        "first": 0x00260100,
        "last": 0x002622FF,
    },
    "PVEnergyProduction": {
        "command": 0x54000200,
        "first": 0x0046C300,
        "last": 0x0046C3FF,
    },
    "SpotDCPower": {
        "command": 0x53800200,
        "first": 0x00251E00,
        "last": 0x00251EFF,
    },
    "SpotDCPower_3": {
        "command": 0x51000200,
        "first": 0x0046C200,
        "last": 0x0046C2FF,
    },
    "SpotACTotalPower": {
        "command": 0x51000200,
        "first": 0x00263F00,
        "last": 0x00263FFF,
    },
    "ChargeStatus": {
        "command": 0x51000200,
        "first": 0x00295A00,
        "last": 0x00295AFF,
    },
    "SpotDCVoltage": {
        "command": 0x53800200,
        "first": 0x00451F00,
        "last": 0x004521FF,
    },
    "SpotACCurrentBackup": {
        "command": 0x51000200,
        "first": 0x40574600,
        "last": 0x405748FF,
    },
    "BatteryInfo_TEMP": {
        "command": 0x51000200,
        "first": 0x00495B00,
        "last": 0x00495B10,
    },
    "BatteryInfo_UDC": {
        "command": 0x51000200,
        "first": 0x00495C00,
        "last": 0x00495C10,
    },
    "BatteryInfo_IDC": {
        "command": 0x51000200,
        "first": 0x00495D00,
        "last": 0x00495D10,
    },
    "BatteryInfo_Charge": {
        "command": 0x51000200,
        "first": 0x00496900,
        "last": 0x00496AFF,
    },
    "BatteryInfo_Capacity": {
        "command": 0x51000200,
        "first": 0x00696E00,
        "last": 0x00696E10,
    },
    "BatteryInfo": {
        "command": 0x51000200,
        "first": 0x00491E00,
        "last": 0x00495DFF,
    },
    "BatteryInfo_3": {
        "command": 0x58020200,
        "first": 0x08822C00,
        "last": 0x08822CFF,
    },
    "BatteryInfo_4": {
        "command": 0x58000200,
        "first": 0x00893700,
        "last": 0x008937FF,
    },
    "BatteryInfo_5": {
        "command": 0x58020200,
        "first": 0x00B18900,
        "last": 0x00B189FF,
    },
    "SpotGridFrequency": {
        "command": 0x51000200,
        "first": 0x00465700,
        "last": 0x004657FF,
    },
    "OperationTime": {
        "command": 0x54000200,
        "first": 0x00462E00,
        "last": 0x00462FFF,
    },
    "InverterTemperature": {
        "command": 0x52000200,
        "first": 0x00237700,
        "last": 0x002377FF,
        "format": "int",
    },
    "MaxACPower": {
        "command": 0x51000200,
        "first": 0x00411E00,
        "last": 0x004120FF,
    },
    "MaxACPower2": {
        "command": 0x51000200,
        "first": 0x00832A00,
        "last": 0x00832AFF,
    },
    "GridRelayStatus": {
        "command": 0x51800200,
        "first": 0x00416400,
        "last": 0x004164FF,
    },
    "BackupRelayStatus": {
        "command": 0x51800200,
        "first": 0x08412500,
        "last": 0x084125FF,
    },
    "GridConection": {
        "command": 0x51800200,
        "first": 0x0046A600,
        "last": 0x0046A6FF,
    },
    "OperatingStatus": {
        "command": 0x51800200,
        "first": 0x08412B00,
        "last": 0x08412BFF,
    },
    "GeneralOperatingStatus": {
        "command": 0x51800200,
        "first": 0x00412800,
        "last": 0x004128FF,
    },
    "WaitingTimeUntilFeedIn": {
        "command": 0x51000200,
        "first": 0x00416600,
        "last": 0x004166FF,
    },
    "DeviceStatus": {
        "command": 0x51800200,
        "first": 0x00214800,
        "last": 0x002148FF,
    },
    "SpotBatteryLoad": {
        "command": 0x54000200,
        "first": 0x00496700,
        "last": 0x004967FF,
    },
    "SpotBatteryUnload": {
        "command": 0x54000200,
        "first": 0x00496800,
        "last": 0x004968FF,
    },
    "EM_1": {
        "command": 0x54000200,
        "first": 0x00462400,
        "last": 0x004628FF,
    },
    "EM_2": {
        "command": 0x54000200,
        "first": 0x40469100,
        "last": 0x404692FF,
    },
    "EM_3": {
        "command": 0x51000200,
        "first": 0x00463600,
        "last": 0x004637FF,
    },
    "EM_4": {
        "command": 0x51000200,
        "first": 0x0046E800,
        "last": 0x0046EDFF,
    },
    "Insulation_1": {
        "command": 0x51020200,
        "first": 0x00254E00,
        "last": 0x00254FFF,
    },
    "Insulation_2": {
        "command": 0x51020200,
        "first": 0x00254F00,
        "last": 0x00254FFF,
    },
    "Firmware": {
        "command": 0x58000200,
        "first": 0x00823400,
        "last": 0x008234FF,
    },
    "energy_production": {
        "command": 0x54000200,
        "first": 0x00260100,
        "last": 0x002622FF,
    },
    "spot_ac_power": {
        "command": 0x51000200,
        "first": 0x00464000,
        "last": 0x004642FF,
    },
    "spot_ac_voltage": {
        "command": 0x51000200,
        "first": 0x00464800,
        "last": 0x004655FF,
    },
}


@dcs.dataclass(dcs.BIG_ENDIAN)
class speedwireHeader:
    """Speedwire header"""

    sma: Annotated[bytes, 4]
    tag42_length: dcs.U16
    tag42_tag0x02A0: dcs.U16
    group1: dcs.U32
    smanet2_length: dcs.U16
    smanet2_tag0x10: dcs.U16 # renamte to id
    protokoll: dcs.U16

    def check6065(self):
        """ Check for 6065 Type.  Size is not checked at this stage """
        return (
            self.sma == b"SMA\x00"
            and self.tag42_length == 4
            and self.tag42_tag0x02A0 == 0x02A0
            and self.group1 == 1
            and self.smanet2_tag0x10 == 0x10
            and self.protokoll == 0x6065
        )

    def isDiscoveryResponse(self):
        """  """
        return (
            self.sma == b"SMA\x00"
            and self.tag42_length == 4
            and self.tag42_tag0x02A0 == 0x02A0
            and self.group1 == 1
            and self.smanet2_length == 2
            and self.smanet2_tag0x10 == 0
            and self.protokoll == 1
        )

@dcs.dataclass(dcs.BIG_ENDIAN)
class speedwireData2Tag:
    smanet2_lengthPayload: dcs.U16
    smanet2_id: dcs.U16
    protokoll: dcs.U16


@dcs.dataclass(dcs.LITTLE_ENDIAN)
class speedwireHeader6065:
    """Speedwire Header2 for 6065 Messages"""

    # https://github.com/RalfOGit/libspeedwire

    # dest_susyid: dcs.U16 #2
    # dest_serial: dcs.U32 # 2+ 4 = 6
    # dest_control: dcs.U16 # 2 4 + 2 = 8
    # src_susyid: dcs.U16 # 2 4 2 2 = 10
    # src_serial: dcs.U32 # 2 4 2 2 4 = 14
    # src_control: dcs.U16 # 2 4 2 2 4 2 = 16

    # unknown1: dcs.U16 # 2
    # susyid: dcs.U16  # 2 +2 = 4
    # serial: dcs.U32  # 2 + 2 + 4 = 8
    # unknown2: Annotated[bytes, 10] # 18

    unknown2: Annotated[bytes, 18]  # 18
    error: dcs.U16
    fragment: dcs.U16
    pktId: dcs.U16
    cmdid: dcs.U32
    firstRegister: dcs.U32
    lastRegister: dcs.U32

    def isLoginResponse(self):
        return self.cmdid == 0xFFFD040D
