const express = require('express');
const router = express.Router();
const rt = require('../ResTool');
const config = require('../../config.json');
const mysql = require('../../libs/mysql_cls');
const tool = require('../../includes/apiTool');
const exec = require('child_process').exec;
const so = require('../../includes/storeObject');

router
    .get('/', (req, res) => {
        res.send({ name: 'WebIO Modbus API' });
    })
    .post('/getmodbuslist', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select * from ??.?? order by `uid` desc";
        let param = [config.db.db5, 'device'];

        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR8000');

            res.api_res = {
                record: tool.checkArray(row)
            };

            return n();
        })
    })
    .post('/getmodbus', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        // if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select * from ??.?? where `uid` = ?";
        let param = [config.db.db5, 'device', arr.data.id];

        res.db.query(query, param, (err, row) => {
            if (err || row.length == 0) return n('ERR8000');

            res.api_res = {
                record: tool.checkArray(row),
                rt: {
                    iolist: [],
                    aioset: []
                }
            };

            let pros = [];

            let iq = "select * from ??.?? where `devuid` = ?";
            let ip = [config.db.db5, 'iolist', row[0].uid];
            pros.push(tool.promiseQuery(res, iq, ip, 'iolist'));

            let aq = "select a.* from ??.?? a\
				left join ??.?? i\
				on \
				a.`iouid`= i.`uid` \
				where \
				i.`devuid` = ?";
            let ap = [config.db.db5, 'aioset', config.db.db5, 'iolist', row[0].uid];
            pros.push(tool.promiseQuery(res, aq, ap, 'aioset'));

            Promise.all(pros)
                .then(r => {
                    for (let i in r) {
                        if (r[i].key == 'iolist') res.api_res.rt.iolist = r[i].data;
                        if (r[i].key == 'aioset') res.api_res.rt.aioset = r[i].data;
                    }
                    return n();
                })
                .catch(err => n('ERR8000'));
        });
    })
    .post('/getporttype', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select * from ??.?? order by `uid` ";
        let param = [config.db.db5, 'porttype'];

        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR8000');
            res.api_res = {
                record: tool.checkArray(row)
            };
            return n();
        });
    })
    .post('/addmodbus', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.name) return n('ERR0026');
        if (!('node' in arr.data)) return n('ERR0038');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let u = '';
        let obj = so.get(req.headers['x-auth-token']);
        if (obj != null && 'user' in obj && 'account' in obj.user) u = obj.user.account;

        let query = "insert into ??.?? (`name`, `node`, `adduser`, `moduser`, `ctime`, `mtime`) values (?,?,?,?, unix_timestamp(), unix_timestamp())";
        let param = [config.db.db5, 'device', arr.data.name, arr.data.node, u, u];

        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR8001');

            res.api_res = {
                record: []
            };

            return n();
        });
    })
    .post('/editmodbus', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');
        if (!arr.data.name) return n('ERR0026');
        if (!('node' in arr.data) || !('original_node' in arr.data)) return n('ERR0038');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select count(*) as num from ??.?? where `node` = ? and `uid` != ?";
        let param = [config.db.db5, 'device', arr.data.node, arr.data.id];
        res.db.query(query, param, (err, row) => {
            if (err || row.length == 0) return n('ERR8000');
            if (row[0].num > 0) return n('ERR0047');

            let u = '';
            let obj = so.get(req.headers['x-auth-token']);
            if (obj != null && 'user' in obj && 'account' in obj.user) u = obj.user.account;

            let query = "update ??.?? set \
				`name` = ?, \
				`node` = ?, \
				`moduser` = ?, \
				`mtime` = unix_timestamp() \
				where \
				`uid` = ?";
            let param = [config.db.db5, 'device', arr.data.name, arr.data.node, u, arr.data.id];
            res.db.query(query, param, (err, row) => {
                if (err) return n('ERR8002');

                let q = "delete from ??.?? where `node` in (?)";
                let p = [config.db.db6, 'jcmbrt', [arr.data.node, arr.data.original_node]];
                res.db.query(q, p, (err, row) => {

                    res.api_res = {
                        record: []
                    };
                    return n();
                });
            })
        })
    })
    .post('/delmodbus', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "delete d,i,s,rt from ??.?? d \
			left join ??.?? i \
			on d.`uid` = i.`devuid` \
			left join ??.?? s \
			on i.`uid` = s.`iouid` \
			left join ??.?? rt \
			on d.`node` = rt.`node` \
			where \
			d.`uid` = ?";
        let param = [config.db.db5, 'device', config.db.db5, 'iolist', config.db.db5, 'aioset', config.db.db6, 'jcmbrt', arr.data.id];
        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR8003');
            res.api_res = {
                record: []
            };
            return n();
        });
    })
    .post('/getiostatus', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');
        if (!arr.data.type) return n('ERR0009');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select rt.*, a.`name` as name from ??.?? rt \
			left join ??.?? d \
			on d.`node` = rt.`node` \
			left join ??.?? i \
			on i.`devuid` = d.`uid` and i.`type` = ? \
            left join ??.?? a \
            on a.`iouid` = i.`uid` \
            and a.`portnum` = rt.`port`\
			where \
			d.`uid` = ? \
			and rt.`type` = ? \
			and i.`uid` is not null ";
        let param = [config.db.db6, 'jcmbrt', config.db.db5, 'device', config.db.db5, 'iolist', arr.data.type, config.db.db5, 'aioset', arr.data.id, arr.data.type];

        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR8000');

            res.api_res = {
                record: tool.checkArray(row)
            };
            return n();
        });
    })
    .post('/getiolist', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select * from ??.?? where `uid` = ? ";
        let param = [config.db.db5, 'iolist', arr.data.id];
        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR8000');

            res.api_res = {
                record: tool.checkArray(row)
            };

            return n();
        });
    })
    .post('/addiolist', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');
        if (!arr.data.type) return n('ERR0009');
        if (!arr.data.addr) return n('ERR0048');
        if (!arr.data.num) return n('ERR0049');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select count(*) as c from ??.?? \
			where \
			`devuid` = ? \
			and `type` = ? \
			and `addr` = ?";
        let param = [config.db.db5, 'iolist', arr.data.id, arr.data.type, arr.data.addr];
        res.db.query(query, param, (err, row) => {
            if (err || row.length == 0) return n('ERR8000');

            if (row[0].c > 0) return n('ERR0054');

            let query = "insert into ??.?? (`devuid`,`type`,`addr`,`num`,`ctime`,`mtime`) values (?, ?, ?, ?, unix_timestamp(), unix_timestamp())";
            let param = [config.db.db5, 'iolist', arr.data.id, arr.data.type, arr.data.addr, arr.data.num];
            res.db.query(query, param, (err, row) => {
                if (err) return n('ERR8001');

                res.api_res = {
                    record: []
                };
                return n();
            });
        });
    })
    .post('/editiolist', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');
        if (!arr.data.addr) return n('ERR0048');
        if (!arr.data.num) return n('ERR0049');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select count(*) as c from ??.?? i \
			left join ??.?? i2 \
			on i2.`type` = i.`type` \
			and i2.`addr` = ? \
			and i2.`devuid` = i.`devuid` \
			and i2.`uid` != ? \
			where \
			i.`uid` = ? \
			and i2.`uid` is not null ";
        let param = [config.db.db5, 'iolist', config.db.db5, 'iolist', arr.data.addr, arr.data.id, arr.data.id];
        res.db.query(query, param, (err, row) => {
            if (err || row.length == 0) return n('ERR8000');
            if (row[0].c > 0) return n('ERR0054');

            let q = "update ??.?? set \
				`addr` = ?, \
				`num` = ?, \
				`mtime` = unix_timestamp() \
				where \
				`uid` = ?";
            let p = [config.db.db5, 'iolist', arr.data.addr, arr.data.num, arr.data.id];
            res.db.query(q, p, (err, row) => {
                if (err) return n('ERR8002');

                res.api_res = {
                    record: []
                };
                return n();
            });
        });
    })
    .post('/deliolist', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "delete i, a from ??.?? i \
			left join ??.?? a \
			on a.`iouid` = i.`uid` \
			where \
			i.`uid` = ?";
        let param = [config.db.db5, 'iolist', config.db.db5, 'aioset', arr.data.id];
        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR8003');

            res.api_res = {
                record: []
            };
            return n();
        });
    })
    .post('/getaiosetlist', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select a.* from ??.?? a \
			left join ??.?? i \
			on a.`iouid` = i.`uid` \
			where \
			i.`uid` = ?";
        let param = [config.db.db5, 'aioset', config.db.db5, 'iolist', arr.data.id];
        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR8000');

            res.api_res = {
                record: tool.checkArray(row)
            };
            return n();
        });
    })
    .post('/getaioset', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select * from ??.?? where `uid` = ?";
        let param = [config.db.db5, 'aioset', arr.data.id];
        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR8000');

            res.api_res = {
                record: tool.checkArray(row)
            };
            return n();
        });
    })
    .post('/delaioset', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "delete from ??.?? where `uid` = ?";
        let param = [config.db.db5, 'aioset', arr.data.id];
        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR8003');
            res.api_res = {
                record: []
            };
            return n();
        });
    })
    .post('/addaioset', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.iouid) return n('ERR0028');
        if (!arr.data.name) return n('ERR0026');
        if (!('portnum' in arr.data)) return n('ERR0048');
        if (!('range_min' in arr.data)) return n('ERR0050');
        if (!('range_max' in arr.data)) return n('ERR0051');
        if (!('scale_min' in arr.data)) return n('ERR0052');
        if (!('scale_max' in arr.data)) return n('ERR0053');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select count(*) as count from ??.?? where `iouid` = ? and `portnum` = ?";
        let param = [config.db.db5, 'aioset', arr.data.iouid, arr.data.portnum];
        res.db.query(query, param, (err, row) => {
            if (err || row.length == 0) return n('ERR8000');

            if (row[0].count > 0) return n('ERR0054');

            let q = "insert into ??.?? (`iouid`, `name`, `portnum`, `range_min`, `range_max`, `scale_min`, `scale_max`, `ctime`, `mtime`) values \
				(?, ?, ?, ?, ?, ?, ?, unix_timestamp(), unix_timestamp())";
            let p = [config.db.db5, 'aioset', arr.data.iouid, arr.data.name, arr.data.portnum, arr.data.range_min, arr.data.range_max, arr.data.scale_min, arr.data.scale_max];
            res.db.query(q, p, (err, row) => {
                if (err) return n('ERR8001');

                res.api_res = {
                    record: []
                };

                return n();
            });
        });
    })
    .post('/editaioset', (req, res, n) => {
        if (!config.permission.modbus) return n('ERR9000');
        if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.id) return n('ERR0028');
        if (!arr.data.iouid) return n('ERR0028');
        if (!arr.data.name) return n('ERR0026');
        if (!arr.data.portnum) return n('ERR0048');
        if (!('range_min' in arr.data)) return n('ERR0050');
        if (!('range_max' in arr.data)) return n('ERR0051');
        if (!('scale_min' in arr.data)) return n('ERR0052');
        if (!('scale_max' in arr.data)) return n('ERR0053');

        res.db = new mysql();
        res.db.user = config.db.user;
        res.db.password = config.db.pass;
        res.db.host = config.db.host;
        res.db.port = config.db.port;
        res.db.database = config.db.db5;
        res.db.connect();

        let query = "select count(*) as count from ??.?? \
            where \
            `iouid` = ? \
            and `portnum` = ? \
            and `uid` != ?";
        let param = [config.db.db5, 'aioset', arr.data.iouid, arr.data.portnum, arr.data.id];
        res.db.query(query, param, (err, row) => {
            if (err || row.length == 0) return n('ERR8000');
            if (row[0].length > 0) return n('ERR0054');

            let query = "update ??.?? set \
                `name` = ?, \
                `portnum` = ?, \
                `range_min` = ?, \
                `range_max` = ?, \
                `scale_min` = ?, \
                `scale_max` = ?, \
                `mtime` = unix_timestamp() \
                where `uid` = ?";
            let param = [config.db.db5, 'aioset', arr.data.name, arr.data.portnum, arr.data.range_min, arr.data.range_max, arr.data.scale_min, arr.data.scale_max, arr.data.id];
            res.db.query(query, param, (err, row) => {
                if (err) return n('ERR8002');

                res.api_res = {
                    record: []
                };
                return n();
            });
        });
    })
    .post('/modbuscmd', (req,res,n) => {
        if (!config.permission.modbus) return n('ERR9000');
        if (!tool.checkPermission(req)) return n('ERR9000');
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if(!arr.data.ip) return n('ERR0010');
        if(!('node' in arr.data) || arr.data.node.length == 0) return n('ERR0038');
        if(!('func' in arr.data) || arr.data.func.length == 0) return n('ERR0055');
        if(!('addr' in arr.data) || arr.data.addr.length == 0) return n('ERR0048');
        if(!('value' in arr.data) || arr.data.value.length == 0) return n('ERR0049');

        let cmd = `mbtcpm ${arr.data.ip} ${arr.data.node} ${arr.data.func} ${arr.data.addr} ${arr.data.value}`;
        res.api_res = {
            record: []
        };
        exec(cmd, (err, stdout, stderr) => {
            let msg =  err ? err.toString() : `${stdout}${stderr}`;
            res.api_res.record.push({msg});

            n();
        })
    })
    .all('*', rt.send);

module.exports = router;