# coding=utf-8
from binascii import b2a_hex, a2b_hex
from datetime import datetime
from decimal import Decimal

from utils import crc_modbus, signed_int_value


class AcrelADW300(object):

    def initial(self, data, protocol, reactor):
        self.protocol = protocol
        self.factory = protocol.factory
        self.reactor = reactor
        self.parse(data)

    def parse(self, data):
        self.data = b2a_hex(data).decode()
        self.operation = self.data[4:6]

    def run_operations(self):
        eval('self.event_{}'.format(self.operation))()

    def event_84(self):
        """解析设备注册包，并回复仪表"""
        meter_id = a2b_hex(self.data[6:46]).decode().replace("\x00", "")
        sim_id = a2b_hex(self.data[46:106]).decode().replace("\x00", "")
        self.factory.clients_content[self.protocol.clientID]["building_id"] = "ADW300"
        self.factory.clients_content[self.protocol.clientID]["gateway_id"] = "ADW300"
        self.factory.clients_content[self.protocol.clientID]["meter_id"] = meter_id
        self.factory.clients_content[self.protocol.clientID]["sim_id"] = sim_id

        response = "7b7b84bf237d7d"
        self.protocol.write(a2b_hex(response))

    def event_93(self):
        """给仪表发送校时包"""
        now = datetime.now()
        now_str = now.strftime("%Y%m%d%H%M%S")
        year = hex(int(now_str[2:4]))[2:].zfill(2)
        month = hex(int(now_str[4:6]))[2:].zfill(2)
        day = hex(int(now_str[6:8]))[2:].zfill(2)
        weekday = hex(now.weekday()+1)[2:].zfill(2)
        hour = hex(int(now_str[8:10]))[2:].zfill(2)
        minute = hex(int(now_str[10:12]))[2:].zfill(2)
        second = hex(int(now_str[12:14]))[2:].zfill(2)

        response = "93" + year + month + day + weekday + hour + minute + second
        crc = crc_modbus(response, left_high=False)
        response = "7b7b" + response + crc + "7d7d"
        self.protocol.write(a2b_hex(response))

    def event_94(self):
        """给仪表发送校时包"""
        now = datetime.now()
        now_str = now.strftime("%Y%m%d%H%M%S")
        year = hex(int(now_str[2:4]))[2:].zfill(2)
        month = hex(int(now_str[4:6]))[2:].zfill(2)
        day = hex(int(now_str[6:8]))[2:].zfill(2)
        weekday = hex(now.weekday()+1)[2:].zfill(2)
        hour = hex(int(now_str[8:10]))[2:].zfill(2)
        minute = hex(int(now_str[10:12]))[2:].zfill(2)
        second = hex(int(now_str[12:14]))[2:].zfill(2)

        response = "94" + year + month + day + weekday + hour + minute + second
        crc = crc_modbus(response, left_high=False)
        response = "7b7b" + response + crc + "7d7d"
        self.protocol.write(a2b_hex(response))

    def event_91(self):
        """解析电能包，保存至数据库，并回复仪表"""
        response = "7b7b917eec7d7d"
        self.protocol.write(a2b_hex(response))
        self.parse_and_save_power()

    def parse_and_save_power(self):
        body = self.data[6:-4]
        power_1 = body[20:204]
        power_2 = body[236:460]

        # 第一段解析
        pt = int(power_1[0:4], base=16)  # 电压变比
        ct = int(power_1[4:8], base=16)  # 电流变比
        tn = int(power_1[8:12], base=16)  # N相温度
        second = int(power_1[12:14], base=16)  # 秒
        minute = int(power_1[14:16], base=16)  # 分
        hour = int(power_1[16:18], base=16)  # 时
        day = int(power_1[18:20], base=16)  # 日
        month = int(power_1[20:22], base=16)  # 月
        year = 2000 + int(power_1[22:24], base=16)  # 年
        ua = int(power_1[24:28], base=16) * 0.1 * pt  # A相电压
        ub = int(power_1[28:32], base=16) * 0.1 * pt  # B相电压
        uc = int(power_1[32:36], base=16) * 0.1 * pt  # C相电压
        uab = int(power_1[36:40], base=16) * 0.1 * pt  # AB线电压
        ubc = int(power_1[40:44], base=16) * 0.1 * pt  # BC线电压
        uca = int(power_1[44:48], base=16) * 0.1 * pt  # CA线电压
        ia = int(power_1[48:52], base=16) * 0.01 * ct  # A相电流
        ib = int(power_1[52:56], base=16) * 0.01 * ct  # B相电流
        ic = int(power_1[56:60], base=16) * 0.01 * ct  # C相电流
        i_vector_sum = int(power_1[60:64], base=16) * 0.01 * ct  # 三相电流矢量和
        pa = signed_int_value(power_1[64:72]) * 0.001 * pt * ct  # A相有功功率
        pb = signed_int_value(power_1[72:80]) * 0.001 * pt * ct  # B相有功功率
        pc = signed_int_value(power_1[80:88]) * 0.001 * pt * ct  # C相有功功率
        p = signed_int_value(power_1[88:96]) * 0.001 * pt * ct  # 总有功功率
        qa = signed_int_value(power_1[96:104]) * 0.001 * pt * ct  # A相无功功率
        qb = signed_int_value(power_1[104:112]) * 0.001 * pt * ct  # B相无功功率
        qc = signed_int_value(power_1[112:120]) * 0.001 * pt * ct  # C相无功功率
        q = signed_int_value(power_1[120:128]) * 0.001 * pt * ct  # 总无功功率
        sa = int(power_1[128:136], base=16) * 0.001 * pt * ct  # A相视在功率
        sb = int(power_1[136:144], base=16) * 0.001 * pt * ct  # B相视在功率
        sc = int(power_1[144:152], base=16) * 0.001 * pt * ct  # C相视在功率
        s = int(power_1[152:160], base=16) * 0.001 * pt * ct  # 总视在功率
        pfa = int(power_1[160:164], base=16) * 0.001  # A相功率因数
        pfb = int(power_1[164:168], base=16) * 0.001  # B相功率因数
        pfc = int(power_1[168:172], base=16) * 0.001  # C相功率因数
        pf = int(power_1[172:176], base=16) * 0.001  # 总功率因数
        di = int(power_1[176:180], base=16)  # DI状态
        f = int(power_1[180:184], base=16) * 0.01  # 电源频率

        # 第二段解析
        ep = int(power_2[0:8], base=16) * 0.01 * pt * ct  # 组合有功总电能
        epi = int(power_2[8:16], base=16) * 0.01 * pt * ct  # 正向有功电能
        epe = int(power_2[16:24], base=16) * 0.01 * pt * ct  # 反向有功电能
        eqi = int(power_2[24:32], base=16) * 0.01 * pt * ct  # 正向无功电能
        eqe = int(power_2[32:40], base=16) * 0.01 * pt * ct  # 反向无功电能
        ep_a = int(power_2[40:48], base=16) * 0.01 * pt * ct  # A相总电能
        epi_a = int(power_2[48:56], base=16) * 0.01 * pt * ct  # A相正向有功电能
        epe_a = int(power_2[56:64], base=16) * 0.01 * pt * ct  # A相反向有功电能
        eqi_a = int(power_2[64:72], base=16) * 0.01 * pt * ct  # A相正向无功电能
        eqe_a = int(power_2[72:80], base=16) * 0.01 * pt * ct  # A相反向无功电能
        ep_b = int(power_2[80:88], base=16) * 0.01 * pt * ct  # B相总电能
        epi_b = int(power_2[88:96], base=16) * 0.01 * pt * ct  # B相正向有功电能
        epe_b = int(power_2[96:104], base=16) * 0.01 * pt * ct  # B相反向有功电能
        eqi_b = int(power_2[104:112], base=16) * 0.01 * pt * ct  # B相正向无功电能
        eqe_b = int(power_2[112:120], base=16) * 0.01 * pt * ct  # B相反向无功电能
        ep_c = int(power_2[120:128], base=16) * 0.01 * pt * ct  # C相总电能
        epi_c = int(power_2[128:136], base=16) * 0.01 * pt * ct  # C相正向有功电能
        epe_c = int(power_2[136:144], base=16) * 0.01 * pt * ct  # C相反向有功电能
        eqi_c = int(power_2[144:152], base=16) * 0.01 * pt * ct  # C相正向无功电能
        eqe_c = int(power_2[152:160], base=16) * 0.01 * pt * ct  # C相反向无功电能
        md = int(power_2[160:168], base=16) * 0.001 * pt * ct  # 当月正向有功最大需量
        md_min = int(power_2[168:170], base=16)  # 分
        md_hour = int(power_2[170:172], base=16)  # 时
        md_day = int(power_2[172:174], base=16)  # 日
        md_month = int(power_2[174:176], base=16)  # 月

        # 数据库存储
        time = datetime(year=year,
                        month=month,
                        day=day,
                        hour=hour,
                        minute=minute,
                        second=second)
        building_code = self.factory.clients_content[self.protocol.clientID]["building_id"]
        gateway_code = self.factory.clients_content[self.protocol.clientID]["gateway_id"]
        meter_code = self.factory.clients_content[self.protocol.clientID]["meter_id"]
        db_data = {'device_imei': '--'.join([building_code, gateway_code, meter_code]),
                   'building_code': building_code,
                   'gateway_code': gateway_code,
                   'meter_code': meter_code,
                   'day': time.strftime("%Y-%m-%d"),
                   'hour': time.strftime("%H"),
                   'device_content': '',
                   'a_dy': ua,
                   'b_dy': ub,
                   'c_dy': uc,
                   'ab_dy': uab,
                   'bc_dy': ubc,
                   'ac_dy': uca,
                   'a_dl': ia,
                   'b_dl': ib,
                   'c_dl': ic,
                   'a_yggl': pa,
                   'b_yggl': pb,
                   'c_yggl': pc,
                   'total_yggl': p,
                   'a_wggl': qa,
                   'b_wggl': qb,
                   'c_wggl': qc,
                   'total_wggl': q,
                   'a_szgl': sa,
                   'b_szgl': sb,
                   'c_szgl': sc,
                   'total_szgl': s,
                   'a_glys': pfa,
                   'b_glys': pfb,
                   'c_glys': pfc,
                   'total_glys': pf,
                   'pl': f,
                   'epi': epi,
                   'a_ygdn': epi_a,
                   'a_wgdn': eqi_a,
                   'b_ygdn': epi_b,
                   'b_wgdn': eqi_b,
                   'c_ygdn': epi_c,
                   'c_wgdn': eqi_c,
                   'md': md,
                   'create_date': time.strftime("%Y-%m-%d %H:%M:%S"),
                   'create_by': 'cc',
                   'update_date': time.strftime("%Y-%m-%d %H:%M:%S"),
                   'update_by': 'cc',
                   'extend_s1': ',,1,0.0',
                   }
        # 生成sql语句并插入数据库
        column = []
        content = []
        for k, v in db_data.items():
            column.append('`%s`' % k)
            if isinstance(v, str):
                content.append("'%s'" % v)
            else:
                content.append(str(v))
        table = 'ld_device_data_%s' % time.strftime("%Y%m")
        col = "(" + ','.join(column) + ")"
        val = "(" + ','.join(content) + ")"
        sql = "INSERT INTO {} {} VALUES {} ".format(table, col, val)
        self.protocol.db.sql(sql)

    def responses_ack(self, status=False, add_header=False):
        pass
