require "log"
require "sys"
require "utils"
require "patch"
require "pack"
require "bit"
siganl = require 'posix.signal'
syswait = require 'posix.sys.wait'
unistd = require 'posix.unistd'
mqtt = require "mosquitto"
base64 = require("base64")
dyutils = require("dyutils")
lpack = require("lua_pack")
require "internal_api"
require "lsqlite3"


local reportsn = ""
local config_table = {}

-- TAG_2728 有功总电量
-- TAG_2734 正向电量
-- TAG_2739 反向电量

-- TAG_272F 总有功功率
-- TAG_2719 A电流
-- TAG_271A B电流
-- TAG_271B C电流

local config_servic_option = {
    TAG_2728 = 0,
    TAG_2734 = 0,
    TAG_2739 = 3,
    TAG_272F = 2,
    TAG_2719 = 5,
    TAG_271A = 5,
    TAG_271B = 5,
    TAG_2725 = 2,
    TAG_2726 = 2,
    TAG_2727 = 2,
    TAG_271C = 2,
    TAG_271D = 2,
    TAG_271E = 2,
    TAG_271F = 2,
    TAG_2720 = 2,
    TAG_2721 = 2,
    TAG_2722 = 4,
    TAG_2723 = 4,
    TAG_2724 = 4,
    TAG_2730 = 2,
    TAG_2731 = 2,
    TAG_2732 = 2,
    TAG_2716 = 0,
    TAG_2717 = 0,
    TAG_2718 = 0,
    TAG_273E = 0,
    TAG_273F = 0
}

local config_sub_dev = {{
    sn = "218812000054_bmsmeter",
    type = "bmsmeter",
    TAG_2728 = 0,
    TAG_2734 = 0,
    TAG_2739 = 0,
    TAG_272F = 0,
    TAG_2719 = 0,
    TAG_271A = 0,
    TAG_271B = 0,
    TAG_2725 = 0,
    TAG_2726 = 0,
    TAG_2727 = 0,
    TAG_271C = 0,
    TAG_271D = 0,
    TAG_271E = 0,
    TAG_271F = 0,
    TAG_2720 = 0,
    TAG_2721 = 0,
    TAG_2722 = 0,
    TAG_2723 = 0,
    TAG_2724 = 0,
    TAG_2730 = 0,
    TAG_2731 = 0,
    TAG_2732 = 0,
    TAG_2716 = 0,
    TAG_2717 = 0,
    TAG_2718 = 0,
    TAG_273E = 0,
    TAG_273F = 0
}, {
    sn = "218812000054_gridmeter",
    type = "gridmeter",
    TAG_2728 = 0,
    TAG_2734 = 0,
    TAG_2739 = 0,
    TAG_272F = 0,
    TAG_2719 = 0,
    TAG_271A = 0,
    TAG_271B = 0,
    TAG_2725 = 0,
    TAG_2726 = 0,
    TAG_2727 = 0,
    TAG_271C = 0,
    TAG_271D = 0,
    TAG_271E = 0,
    TAG_271F = 0,
    TAG_2720 = 0,
    TAG_2721 = 0,
    TAG_2722 = 0,
    TAG_2723 = 0,
    TAG_2724 = 0,
    TAG_2730 = 0,
    TAG_2731 = 0,
    TAG_2732 = 0,
    TAG_2716 = 0,
    TAG_2717 = 0,
    TAG_2718 = 0,
    TAG_273E = 0,
    TAG_273F = 0
}}

local config_serviceup = {{
    iotidentifier = nil,
    identifier = "yougongzongdianliang",
    tags = {"TAG_2728", "TAG_2734", "TAG_2739"}
}, {
    iotidentifier = nil,
    identifier = "zongyougonggonglu",
    tags = {"TAG_272F"}
}, {
    iotidentifier = nil,
    identifier = "sanxiangcv",
    tags = {"TAG_2716", "TAG_2717", "TAG_2718", "TAG_2719", "TAG_271A", "TAG_271B"}
}, {
    iotidentifier = nil,
    identifier = "sanxianggongluxinxi",
    tags = {"TAG_271C", "TAG_271D", "TAG_271E", "TAG_272F", "TAG_271F", "TAG_2720", "TAG_2721", "TAG_2730", "TAG_2725",
            "TAG_2726", "TAG_2727", "TAG_2731", "TAG_2722", "TAG_2723", "TAG_2724",
            "TAG_2732"}
}}

local nodes_cfg =
    '[{"connect_port":"VINTF_TCP","depth":0,"product_key":"206627059","sn":"218812000054_loadmeter","template_id":"206627059"}]'

local function nodes_show(nodes_cfg)
    local nodejs = cjson.decode(nodes_cfg)
    for i, v in ipairs(nodejs) do
        log.info(i, v.connect_port, v.sn, v.product_key)
    end
end

local function config_init(nodes_cfg,sn)
    local nodejs = cjson.decode(nodes_cfg)
    config_table.mysn = nodejs[1].sn
    config_table.gwsn = io.getGatewayID()
    config_table.connect_port = nodejs[1].connect_port
    log.info("gwsn:", config_table.gwsn, "mysn:", config_table.mysn)
    config_table.dev = config_sub_dev
    log.info("devnum:", #config_table.dev)
    config_table.upservice = config_serviceup
    for i, v in ipairs(config_table.dev) do
        log.info("dev :", i, v.sn)
        v.sn = sn.."_"..v.type
        if v.type == "bmsmeter" then
            reportsn = v.sn
        end

    end
    for i, v in ipairs(config_table.upservice) do
        log.info("upservice :", i, v.identifier)
        for i = 0, #v.tags do
            print(v.tags[i])
        end
    end
end

local function report_process(msg)
    local tags = {}
    local report = {}
    local grid = {}
    local bms = {}
    if msg.sn == reportsn then
        for _, v in ipairs(config_table.upservice) do
            if v.identifier == msg.identifier then
                tags = v.tags
                for _, dev in ipairs(config_table.dev) do
                    if msg.sn == dev.sn then
                        bms = dev
                        for i = 1, #v.tags do
                            report[v.tags[i]] = dev[v.tags[i]]
                        end
                    else
                        for i = 1, #v.tags do
                            grid[v.tags[i]] = dev[v.tags[i]]
                        end
                    end
                end
            end
        end
    else
        return
    end

    for i = 1, #tags do
        if config_servic_option[tags[i]] == 1 then
            if bms["TAG_272F"] < 0 then
            report[tags[i]] = report[tags[i]] + grid[tags[i]]
            else
                report[tags[i]] = grid[tags[i]] - report[tags[i]]
            end
        end
        -- if config_servic_option[tags[i]] == 2 then
        --     if bms["TAG_272F"] < 0 then
        --         report[tags[i]] = grid[tags[i]] - report[tags[i]]
        --   else
        --         report[tags[i]] = grid[tags[i]] + report[tags[i]]
        --   end
        -- end
        if config_servic_option[tags[i]] == 2 then      
        --    if bms["TAG_272F"] < 0 then
                report[tags[i]] = grid[tags[i]] - report[tags[i]]
        --    else^M                                   
        --      report[tags[i]] = grid[tags[i]] + report[tags[i]]
        --    end^M                         
        end                                   
        if config_servic_option[tags[i]] == 5 then
            if bms["TAG_272F"] < 0 then           
                report[tags[i]] = grid[tags[i]] - report[tags[i]]
            else                                     
                 report[tags[i]] = grid[tags[i]] + report[tags[i]]
            end                     
        end
        if config_servic_option[tags[i]] == 3 then
            report[tags[i]] = grid["TAG_2734"] - report["TAG_2739"]
            report[tags[i]] = report[tags[i]] + report["TAG_2734"]
            report["TAG_2734"] = report[tags[i]]
            report["TAG_2728"] = 0
            -- report[tags[i]] =  grid[tags[i]] - report["TAG_2739"]
            if report[tags[i]] < 0 then
                return
            end
        end
        if config_servic_option[tags[i]] == 4 then
            report[tags[i]]  = grid[tags[i]]
        end
    end
    local msg1 = cjson.encode(report)
    log.info("report_iot:", msg1, config_table.gwsn, config_table.mysn, config_table.connect_port, msg.identifier)
    internal_api.service_response(config_table.gwsn, config_table.mysn, config_table.connect_port, msg.identifier, msg1,
        msg.mi)
end

local function port2pp(playlad, len)
    local msg = cjson.decode(playlad)
    local flag = 0
    log.info("port2pp:", msg.identifier, msg.sn)
    local data = cjson.decode(msg.tag_node)
    for _, v in ipairs(config_table.upservice) do
        if (v.identifier == msg.identifier) then
            for _, dev in ipairs(config_table.dev) do
                if dev.sn == msg.sn then
                    for i = 0, #v.tags do
                        if data[v.tags[i]] ~= nil then
                            dev[v.tags[i]] = data[v.tags[i]]
                            print(v.tags[i], data[v.tags[i]])
                        end
                    end
                    flag = 1
                    break
                end
            end
            break
        end
    end
    if flag == 1 then
        report_process(msg)
    end
end

local function iot2pp(playlad, len)
    local msg = cjson.decode(playlad)
    log.info("port2pp:", msg.identifier)
end

local function on_mqtt_msg(topic, payload)
    if string.find(topic, "data/service") then
        local ret, err = pcall(port2pp, payload, #payload)
        if not ret then
            log.warn("mqtt.recv", err)
        end
    elseif string.find(topic, "data/Set_Rglt") then
        local ret, err = pcall(iot2pp, payload, #payload)
        if not ret then
            log.warn("mqtt.recv", err)
        end
    else

    end
end

local function mqtt_init()
    local subscribe = {}
    local devtopic = {}
    for i, v in ipairs(config_table.dev) do
        for k, vv in ipairs(config_table.upservice) do
            devtopic = string.format("ipc/%s/+/device/%s/data/service/%s", config_table.gwsn, v.sn, vv.identifier)
            table.insert(subscribe, devtopic)
        end
    end
    devtopic = string.format("ipc/%s/+/device/%s/data/Set_Rglt", config_table.gwsn, config_table.mysn)
    table.insert(subscribe, devtopic)
    for i, v in ipairs(subscribe) do
        log.info(i, v)
    end
    internal_api.mqtt_session("localhost", 1883, nil, nil, subscribe, on_mqtt_msg)
end

local function handler()
    local pid, status, code = syswait.wait(-1, syswait.WNOHANG)
    log.error('system exit', pid, status, code) -- 打印不出来
    os.exit(0)
end

local function signal_init()
    siganl.signal(siganl.SIGKILL, handler)
    siganl.signal(siganl.SIGHUP, handler)
end

local function startserver()
    -- 启动系统框架
    sys.init(0, 0)
    sys.run()
end

local function main(nodes_cfg, sn)
    signal_init()
    -- nodes_show(nodes_cfg)
    config_init(nodes_cfg,sn)
    mqtt_init()
    startserver()
end

main(arg[1] ,arg[2])
