"""Tuya Din Power Meter."""
import logging
from zigpy.profiles import zha
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Groups, Ota, Scenes, Time
from zigpy.zcl.clusters.homeautomation import ElectricalMeasurement
from zigpy.zcl.clusters.smartenergy import Metering

from zhaquirks import Bus, LocalDataCluster
from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.tuya import TuyaManufClusterAttributes, TuyaOnOff, TuyaSwitch

TUYA_TOTAL_ENERGY_ATTR = 0x0211 #energy
TUYA_CURRENT_ATTR = 0x0212 #current
TUYA_POWER_ATTR = 0x0213 #power
TUYA_VOLTAGE_ATTR = 0x0214 #voltaje
TUYA_DIN_SWITCH_ATTR = 0x0101 #switch

SWITCH_EVENT = "switch_event"

"""Hiking Power Meter Attributes"""
HIKING_DIN_SWITCH_ATTR = 0x0110
HIKING_TOTAL_ENERGY_DELIVERED_ATTR = 0x0201
HIKING_TOTAL_ENERGY_RECEIVED_ATTR = 0x0266
HIKING_VOLTAGE_CURRENT_ATTR = 0x0006
HIKING_POWER_ATTR = 0x0267
HIKING_FREQUENCY_ATTR = 0x0269
HIKING_POWER_FACTOR_ATTR = 0x026F
HIKING_TOTAL_REACTIVE_ATTR = 0x026D
HIKING_REACTIVE_POWER_ATTR = 0x026E

"""MatSee Power Meter Attributes"""
MATSEE_DPID_POWER_TOTAL_ID_ATTR = 0x0273
MATSEE_DPID_POWER_ID_A_ATTR = 0x0265
MATSEE_DPID_POWER_ID_B_ATTR = 0x0269
MATSEE_DPID_POWER_DIRECTION_ID_A_ATTR = 0x0266
MATSEE_DPID_POWER_DIRECTION_ID_B_ATTR = 0x0268
MATSEE_DPID_FORWARD_ENERGY_TOTAL_A_ATTR = 0x026A
MATSEE_DPID_REVERSE_ENERGY_TOTAL_A_ATTR = 0x026B
MATSEE_DPID_FORWARD_ENERGY_TOTAL_B_ATTR = 0x026C
MATSEE_DPID_REVERSE_ENERGY_TOTAL_B_ATTR = 0x026D
MATSEE_DPID_POWER_FACTOR_A_ATTR = 0x026E
MATSEE_DPID_POWER_FACTOR_B_ATTR = 0x0279
MATSEE_DPID_POWER_FREQ_ATTR = 0x026F
MATSEE_DPID_VOLTAGE_A_ATTR = 0x0270
MATSEE_DPID_CURRENT_A_ATTR = 0x0271
MATSEE_DPID_CURRENT_B_ATTR = 0x0272
MATSEE_DPID_UPDATE_RATE_ATTR = 0x0281
MATSEE_DPID_VOLTAGE_A_COEF_ATTR = 0x0274
MATSEE_DPID_CURRENT_A_COEF_ATTR = 0x0275
MATSEE_DPID_POWER_A_COEF_ATTR = 0x0276
MATSEE_DPID_ENERGY_A_COEF_ATTR = 0x0277
MATSEE_DPID_ENERGY_A_COEF_REV_ATTR = 0x027F
MATSEE_DPID_FREQ_COEF_ATTR = 0x027A
MATSEE_DPID_CURRENT_B_COEF_ATTR = 0x027B
MATSEE_DPID_POWER_B_COEF_ATTR = 0x027C
MATSEE_DPID_ENERGY_B_COEF_ATTR = 0x027D
MATSEE_DPID_ENERGY_B_COEF_REV_ATTR = 0x0280

_LOGGER = logging.getLogger(__name__)

class TuyaManufClusterDinPower(TuyaManufClusterAttributes):
    """Manufacturer Specific Cluster of the Tuya Power Meter device."""

    attributes = {
        TUYA_TOTAL_ENERGY_ATTR: ("energy", t.uint32_t, True),
        TUYA_CURRENT_ATTR: ("current", t.int16s, True),
        TUYA_POWER_ATTR: ("power", t.uint16_t, True),
        TUYA_VOLTAGE_ATTR: ("voltage", t.uint16_t, True),
        TUYA_DIN_SWITCH_ATTR: ("switch", t.uint8_t, True),
    }

    def _update_attribute(self, attrid, value):
        super()._update_attribute(attrid, value)
        if attrid == TUYA_TOTAL_ENERGY_ATTR:
            self.endpoint.smartenergy_metering.energy_deliver_reported(value / 100)
        elif attrid == TUYA_CURRENT_ATTR:
            self.endpoint.electrical_measurement.current_reported(value)
        elif attrid == TUYA_POWER_ATTR:
            self.endpoint.electrical_measurement.power_reported(value / 10)
        elif attrid == TUYA_VOLTAGE_ATTR:
            self.endpoint.electrical_measurement.voltage_reported(value / 10)
        elif attrid == TUYA_DIN_SWITCH_ATTR:
            self.endpoint.device.switch_bus.listener_event(
                SWITCH_EVENT, self.endpoint.endpoint_id, value
            )


class TuyaPowerMeasurement(LocalDataCluster, ElectricalMeasurement):
    """Custom class for power, voltage and current measurement."""

    cluster_id = ElectricalMeasurement.cluster_id

    POWER_ID = 0x050B
    VOLTAGE_ID = 0x0505
    CURRENT_ID = 0x0508
    REACTIVE_POWER_ID = 0x050E
    AC_FREQUENCY_ID = 0x0300
    TOTAL_REACTIVE_POWER_ID = 0x0305
    POWER_FACTOR_ID = 0x0510

    AC_VOLTAGE_MULTIPLIER = 0x0600
    AC_VOLTAGE_DIVISOR = 0x0601
    AC_CURRENT_MULTIPLIER = 0x0602
    AC_CURRENT_DIVISOR = 0x0603
    AC_FREQUENCY_MULTIPLIER = 0x0400
    AC_FREQUENCY_DIVISOR = 0x0401

    _CONSTANT_ATTRIBUTES = {
        AC_VOLTAGE_MULTIPLIER: 1,
        AC_VOLTAGE_DIVISOR: 10,
        AC_CURRENT_MULTIPLIER: 1,
        AC_CURRENT_DIVISOR: 1000,
        AC_FREQUENCY_MULTIPLIER: 1,
        AC_FREQUENCY_DIVISOR: 100,
    }

    def voltage_reported(self, value):
        """Voltage reported."""
        self._update_attribute(self.VOLTAGE_ID, value)

    def power_reported(self, value):
        """Power reported."""
        self._update_attribute(self.POWER_ID, value)

    def power_factor_reported(self, value):
        """Power Factor reported."""
        self._update_attribute(self.POWER_FACTOR_ID, value)

    def reactive_power_reported(self, value):
        """Reactive Power reported."""
        self._update_attribute(self.REACTIVE_POWER_ID, value)

    def current_reported(self, value):
        """Ampers reported."""
        self._update_attribute(self.CURRENT_ID, value)

    def frequency_reported(self, value):
        """AC Frequency reported."""
        self._update_attribute(self.AC_FREQUENCY_ID, value)

    def reactive_energy_reported(self, value):
        """Summation Reactive Energy reported."""
        self._update_attribute(self.TOTAL_REACTIVE_POWER_ID, value)


class TuyaElectricalMeasurement(LocalDataCluster, Metering):
    """Custom class for total energy measurement."""

    cluster_id = Metering.cluster_id
    CURRENT_DELIVERED_ID = 0x0000
    CURRENT_RECEIVED_ID = 0x0001
    #CURRENT_TIER1_DELIVERED_ID = 0x0100
    POWER_WATT = 0x0000

    """Setting unit of measurement."""
    _CONSTANT_ATTRIBUTES = {0x0300: POWER_WATT}

    def energy_deliver_reported(self, value):
        """Summation Energy Deliver reported."""
        self._update_attribute(self.CURRENT_DELIVERED_ID, value)

    def energy_receive_reported(self, value):
        """Summation Energy Receive reported."""
        self._update_attribute(self.CURRENT_RECEIVED_ID, value)

    #def energy_tier1_deliver_reported(self, value):
    #    """Summation Energy Tier1 Receive reported."""
    #    self._update_attribute(self.CURRENT_TIER1_DELIVERED_ID, value)

class HikingManufClusterDinPower(TuyaManufClusterAttributes):
    """Manufacturer Specific Cluster of the Hiking Power Meter device."""

    attributes = {
        HIKING_DIN_SWITCH_ATTR: ("switch", t.uint8_t, True),
        HIKING_TOTAL_ENERGY_DELIVERED_ATTR: ("energy_delivered", t.uint32_t, True),
        HIKING_TOTAL_ENERGY_RECEIVED_ATTR: ("energy_received", t.uint16_t, True),
        HIKING_VOLTAGE_CURRENT_ATTR: ("voltage_current", t.uint32_t, True),
        HIKING_POWER_ATTR: ("power", t.uint16_t, True),
        HIKING_FREQUENCY_ATTR: ("frequency", t.uint16_t, True),
        HIKING_TOTAL_REACTIVE_ATTR: ("total_reactive_energy", t.int32s, True),
        HIKING_REACTIVE_POWER_ATTR: ("reactive_power", t.int16s, True),
        HIKING_POWER_FACTOR_ATTR: ("power_factor", t.uint16_t, True),
    }

    def _update_attribute(self, attrid, value):
        super()._update_attribute(attrid, value)
        if attrid == HIKING_DIN_SWITCH_ATTR:
            self.endpoint.device.switch_bus.listener_event(SWITCH_EVENT, 16, value)
        elif attrid == HIKING_TOTAL_ENERGY_DELIVERED_ATTR:
            self.endpoint.smartenergy_metering.energy_deliver_reported(value / 100)
        elif attrid == HIKING_TOTAL_ENERGY_RECEIVED_ATTR:
            self.endpoint.smartenergy_metering.energy_receive_reported(value / 100)
        elif attrid == HIKING_VOLTAGE_CURRENT_ATTR:
            self.endpoint.electrical_measurement.current_reported(value >> 16)
            self.endpoint.electrical_measurement.voltage_reported(
                (value & 0x0000FFFF) / 10
            )
        elif attrid == HIKING_POWER_ATTR:
            self.endpoint.electrical_measurement.power_reported(value)
        elif attrid == HIKING_FREQUENCY_ATTR:
            self.endpoint.electrical_measurement.frequency_reported(value)
        elif attrid == HIKING_TOTAL_REACTIVE_ATTR:
            self.endpoint.electrical_measurement.reactive_energy_reported(value)
        elif attrid == HIKING_REACTIVE_POWER_ATTR:
            self.endpoint.electrical_measurement.reactive_power_reported(value)
        elif attrid == HIKING_POWER_FACTOR_ATTR:
            self.endpoint.electrical_measurement.power_factor_reported(value / 10)

class MatSeeManufClusterDinPower(TuyaManufClusterAttributes):
    """Manufacturer Specific Cluster of the Hiking Power Meter device."""
    _LOGGER.debug("PRUEBA MatSeeManufClusterDinPower")

    attributes = {
        HIKING_DIN_SWITCH_ATTR: ("switch", t.uint8_t, True),
        MATSEE_DPID_REVERSE_ENERGY_TOTAL_A_ATTR: ("energy_delivered", t.uint32_t, True),
        MATSEE_DPID_FORWARD_ENERGY_TOTAL_A_ATTR: ("energy_received", t.uint32_t, True),
        MATSEE_DPID_REVERSE_ENERGY_TOTAL_B_ATTR: ("energy_delivered_b", t.uint32_t, True),
        MATSEE_DPID_FORWARD_ENERGY_TOTAL_B_ATTR: ("energy_received_b", t.uint32_t, True),
        MATSEE_DPID_VOLTAGE_A_ATTR: ("voltage_current", t.uint32_t, True),
        MATSEE_DPID_POWER_ID_A_ATTR: ("power", t.uint32_t, True),
        MATSEE_DPID_POWER_ID_B_ATTR: ("power_b", t.uint32_t, True),
        MATSEE_DPID_POWER_FREQ_ATTR: ("frequency", t.uint32_t, True),
        MATSEE_DPID_POWER_TOTAL_ID_ATTR: ("total_reactive_energy", t.int32s, True),
        MATSEE_DPID_POWER_A_COEF_ATTR: ("reactive_power", t.uint32_t, True),
        MATSEE_DPID_POWER_B_COEF_ATTR: ("reactive_power_b", t.uint32_t, True),
        MATSEE_DPID_POWER_FACTOR_A_ATTR: ("power_factor", t.uint32_t, True),
        MATSEE_DPID_POWER_FACTOR_B_ATTR: ("power_factor_b", t.uint32_t, True),
        MATSEE_DPID_CURRENT_A_ATTR: ("current", t.uint32_t, True),
        MATSEE_DPID_CURRENT_B_ATTR: ("current_b", t.uint32_t, True),
        MATSEE_DPID_POWER_DIRECTION_ID_A_ATTR: ("power_direction", t.uint8_t, True),
        MATSEE_DPID_POWER_DIRECTION_ID_B_ATTR: ("power_direction_b", t.uint8_t, True),
        MATSEE_DPID_UPDATE_RATE_ATTR: ("update_rate", t.uint32_t, True),
        MATSEE_DPID_VOLTAGE_A_COEF_ATTR: ("voltage_coef", t.uint32_t, True),
        MATSEE_DPID_CURRENT_A_COEF_ATTR: ("current_coef", t.uint32_t, True),
        MATSEE_DPID_CURRENT_B_COEF_ATTR: ("current_coef_b", t.uint32_t, True),
        MATSEE_DPID_ENERGY_A_COEF_ATTR: ("energy_coef", t.uint32_t, True),
        MATSEE_DPID_ENERGY_B_COEF_ATTR: ("energy_coef_b", t.uint32_t, True),
        MATSEE_DPID_ENERGY_A_COEF_REV_ATTR: ("energy_coef_rev", t.uint32_t, True),
        MATSEE_DPID_ENERGY_B_COEF_REV_ATTR: ("energy_coef_rev_b", t.uint32_t, True),
        MATSEE_DPID_FREQ_COEF_ATTR: ("frequency_coef", t.uint32_t, True),
    }

    def _update_attribute(self, attrid, value):
        super()._update_attribute(attrid, value)
        if attrid == HIKING_DIN_SWITCH_ATTR:
            self.endpoint.device.switch_bus.listener_event(SWITCH_EVENT, 16, value)
        elif attrid == MATSEE_DPID_REVERSE_ENERGY_TOTAL_A_ATTR:
            self.endpoint.smartenergy_metering.energy_deliver_reported(value / 100)
        elif attrid == MATSEE_DPID_FORWARD_ENERGY_TOTAL_A_ATTR:
            self.endpoint.smartenergy_metering.energy_receive_reported(value / 100)
        #elif attrid == MATSEE_DPID_REVERSE_ENERGY_TOTAL_B_ATTR:
        #    self.endpoint.smartenergy_metering.energy_tier1_deliver_reported(value / 100)
        elif attrid == MATSEE_DPID_CURRENT_A_ATTR:
            self.endpoint.electrical_measurement.current_reported(value)
        #elif attrid == MATSEE_DPID_CURRENT_B_ATTR:
        #    self.endpoint.electrical_measurement.current_reported((value & 0x0000FFFF)/1000)
        elif attrid == MATSEE_DPID_VOLTAGE_A_ATTR:
            #self.endpoint.electrical_measurement.current_reported(value >> 16)
            #self.endpoint.electrical_measurement.current_reported((value & 0x0000FFFF) / 10)
            self.endpoint.electrical_measurement.voltage_reported(
                value
            )
        elif attrid == MATSEE_DPID_POWER_ID_A_ATTR:
            self.endpoint.electrical_measurement.power_reported(value)
        elif attrid == MATSEE_DPID_POWER_FREQ_ATTR:
            self.endpoint.electrical_measurement.frequency_reported(value)
        elif attrid == MATSEE_DPID_POWER_TOTAL_ID_ATTR:
            self.endpoint.electrical_measurement.reactive_energy_reported(value)
        elif attrid == MATSEE_DPID_POWER_A_COEF_ATTR:
            self.endpoint.electrical_measurement.reactive_power_reported(value)
        elif attrid == MATSEE_DPID_POWER_FACTOR_A_ATTR:
            self.endpoint.electrical_measurement.power_factor_reported(value / 100)


class TuyaPowerMeter(TuyaSwitch):
    """Tuya power meter device."""

    def __init__(self, *args, **kwargs):
        """Init device."""
        self.switch_bus = Bus()
        super().__init__(*args, **kwargs)

    signature = {
        # "node_descriptor": "<NodeDescriptor byte1=1 byte2=64 mac_capability_flags=142 manufacturer_code=4098
        #                       maximum_buffer_size=82 maximum_incoming_transfer_size=82 server_mask=11264
        #                       maximum_outgoing_transfer_size=82 descriptor_capability_field=0>",
        # device_version=1
        # input_clusters=[0x0000, 0x0004, 0x0005, 0xef00]
        # output_clusters=[0x000a, 0x0019]
        MODELS_INFO: [
            ("_TZE200_byzdayie", "TS0601"),
            ("_TZE200_ewxhg6o9", "TS0601"),
            ("_TZE204_81yrt3lo", "TS0601"),
        ],
        ENDPOINTS: {
            # <SimpleDescriptor endpoint=1 profile=260 device_type=51
            # device_version=1
            # input_clusters=[0, 4, 5, 61184]
            # output_clusters=[10, 25]>
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaManufClusterAttributes.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaManufClusterDinPower,
                    TuyaPowerMeasurement,
                    TuyaElectricalMeasurement,
                    TuyaOnOff,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            }
        }
    }


class HikingPowerMeter(TuyaSwitch):
    """Hiking Power Meter Device - DDS238-2."""

    signature = {
        # "node_descriptor": "<NodeDescriptor byte1=1 byte2=64 mac_capability_flags=142 manufacturer_code=4098
        #                       maximum_buffer_size=82 maximum_incoming_transfer_size=82 server_mask=11264
        #                       maximum_outgoing_transfer_size=82 descriptor_capability_field=0>",
        # device_version=1
        # input_clusters=[0x0000, 0x0004, 0x0005, 0xef00]
        # output_clusters=[0x000a, 0x0019]
        MODELS_INFO: [("_TZE200_bkkmqmyo", "TS0601")],
        ENDPOINTS: {
            # <SimpleDescriptor endpoint=1 profile=260 device_type=51
            # device_version=1
            # input_clusters=[0, 4, 5, 61184]
            # output_clusters=[10, 25]>
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaManufClusterAttributes.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            }
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    HikingManufClusterDinPower,
                    TuyaElectricalMeasurement,
                    TuyaPowerMeasurement,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            16: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    TuyaOnOff,
                ],
                OUTPUT_CLUSTERS: [],
            },
        }
    }

class TuyaPowerMeter_GPP(TuyaSwitch):
    """Tuya power meter device."""

    def __init__(self, *args, **kwargs):
        """Init device."""
        self.switch_bus = Bus()
        super().__init__(*args, **kwargs)

    signature = {
        # "node_descriptor": "<NodeDescriptor byte1=1 byte2=64 mac_capability_flags=142 manufacturer_code=4098
        #                       maximum_buffer_size=82 maximum_incoming_transfer_size=82 server_mask=11264
        #                       maximum_outgoing_transfer_size=82 descriptor_capability_field=0>",
        # device_version=1
        # input_clusters=[0x0000, 0x0004, 0x0005, 0xef00]
        # output_clusters=[0x000a, 0x0019]
        MODELS_INFO: [
            ("_TZE200_lsanae15", "TS0601"),
            ("_TZE204_81yrt3lo", "TS0601"),
        ],
        ENDPOINTS: {
            # <SimpleDescriptor endpoint=1 profile=260 device_type=51
            # device_version=1
            # input_clusters=[0, 4, 5, 61184]
            # output_clusters=[10, 25]>
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    TuyaManufClusterAttributes.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            242: {
                # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
                # input_clusters=[]
                # output_clusters=[33]
                PROFILE_ID: 41440,
                DEVICE_TYPE: 97,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
            },
        },
    }

    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    Groups.cluster_id,
                    Scenes.cluster_id,
                    MatSeeManufClusterDinPower,
                    TuyaPowerMeasurement,
                    TuyaElectricalMeasurement,
                    TuyaOnOff,
                ],
                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
            },
            242: {
                # <SimpleDescriptor endpoint=242 profile=41440 device_type=97
                # input_clusters=[]
                # output_clusters=[33]
                PROFILE_ID: 41440,
                DEVICE_TYPE: 97,
                INPUT_CLUSTERS: [],
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
            },
        }
    }