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

router
    .get('/', (req, res, n) => {
        // 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.db1;
        // res.db.connect();

        res.send({ name: 'WebIO System API' });
    })
    .post('/getnetwork', (req, res, n) => {
        fs.exists(config.cmdpath.sysinfo, (exists) => {
            if (!exists) return n('ERR0014');
            fs.readFile(config.cmdpath.sysinfo, (err, d) => {
                if (err) return n('ERR0014');
                let str = d.toString().split(/\n/);
                let arr = {};
                for (var i in str) {
                    if (!str[i].trim()) continue;
                    let t = str[i].split(' ');
                    if (t.langth < 2) continue;
                    arr[t[0]] = t[1];
                }

                let data = {};
                data.record = [arr];
                res.api_res = data;
                return n();
            });
        });
    })
    .post('/updatenetwork', (req, res, n) => {
        let arr = req.body;
        if (!tool.checkPermission(req)) return n('ERR9000');
        if (!arr.data) return n('ERR0000');
        if (!arr.data.type) return n('ERR0009');
        if (arr.data.type == 'manual') {
            if (!arr.data.ip) return n('ERR0010');
            if (!arr.data.netmask) return n('ERR0011');
            if (!arr.data.gateway) return n('ERR0012');
            if (!arr.data.dns) return n('ERR0013');
        }

        let cmd = '';
        if (arr.data.type == 'manual') {
            cmd = `echo "${arr.data.ip}" "${arr.data.gateway}" "${arr.data.netmask}" "${arr.data.dns}" > ${config.cmdpath.manualip}`;
        } else {
            cmd = `touch ${config.cmdpath.dhcpip}`;
        }

        if (cmd.length > 0) {
            exec(cmd, (err, sout, serr) => {
                let data = {};
                data.record = [];
                res.api_res = data;
                return n();
            });
        }
    })
    .post('/gettime', (req, res, n) => {
        let cmd = 'date +%s';
        exec(cmd, (err, sout, serr) => {
            let time = parseInt(sout);
            let data = {};
            data.record = [{ time }];
            res.api_res = data;
            return n();
        });
    })
    .post('/updatetime', (req, res, n) => {
        let arr = req.body;
        if (!tool.checkPermission(req)) return n('ERR9000');
        if (!arr.data) return n('ERR0000');
        if (!arr.data.time || !/^[0-9]{12}$/.test(arr.data.time)) return n('ERR0015');

        let cmd = `echo "${arr.data.time}" > ${config.cmdpath.settime}`;

        exec(cmd, (err, sout, serr) => {
            let data = {};
            data.record = [];
            res.api_res = data;
            return n();
        });
    })
    .post('/login', (req, res, n) => {
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        if (!arr.data.account) return n('ERR0016');
        if (!arr.data.password) return n('ERR0017');

        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.db1;
        res.db.connect();

        let query = "select * from ??.?? where `account` = ? and `user_password` = ?";
        res.db.query(query, [config.db.db1, 'userlist', arr.data.account, arr.data.password], (err, row) => {
            if (err) return n('ERR8000');
            if (row.length == 0) return n('ERR0019');
            delete row[0]['user_password'];

            let token = '';
            while (true) {
                token = crypt.random(15);
                if (!so.chkKey(token)) break;
            }
            so.set(token, { user: row[0] });

            let data = {};
            data.record = row;
            data.rt = {}
            data.rt.permission = [];

            let tmp = {};
            for(let i in config.permission) {
                if(config.permission[i]){
                    tmp[i] = true;
                }
            }
            data.rt.permission.push(tmp);

            data.token = token;
            res.api_res = data;
            return n();
        });
    })
    .post('/logout', (req, res, n) => {
        let token = req.headers['x-auth-token'];
        if (token) {
            so.del(token);
        }

        let data = {};
        data.record = [];
        res.api_res = data;
        return n();
    })
    .post(['/getuserlist', '/getuser'], (req, res, n) => {
        let s = false;
        let arr = req.body;
        if (req.url == '/getuser') {
            s = true;
            if (!arr.data) return n('ERR0000');
            if (!arr.data.account) return n('ERR0016');
        }
        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.db1;
        res.db.connect();

        let query = "select * from ??.??";
        let param = [config.db.db1, 'userlist']

        if (s) {
            query += " where `account` = ?";
            param.push(arr.data.account);
        }

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

            for (var i in row) {
                delete row[i]['user_password'];
            }

            let data = {};
            data.record = row;
            res.api_res = data;
            return n();
        })
    })
    .post('/deluser', (req, res, n) => {
        let arr = req.body;
        if (!tool.checkPermission(req)) return n('ERR9000');
        if (!arr.data) return n('ERR0000');
        if (!arr.data.account) return n('ERR0016');
        if (arr.data.account == 'admin') return n('ERR0037');

        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.db1;
        res.db.connect();

        let query = "delete from ??.?? where `account` = ?";
        let param = [config.db.db1, 'userlist', arr.data.account];
        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR0020');

            let data = {};
            data.record = [];
            res.api_res = data;
            return n();
        });
    })
    .post('/edituser', (req, res, n) => {
        let arr = req.body;
        if (!tool.checkPermission(req)) return n('ERR9000');
        if (!arr.data) return n('ERR0000');
        if (!arr.data.account) return n('ERR0016');

        let w = arr.data.write_privilege && arr.data.write_privilege == '1' ? 1 : 0;
        let r = arr.data.read_privilege && arr.data.read_privilege == '1' ? 1 : 0;
        let pass = typeof arr.data.password == 'string' && arr.data.password.length > 0 ? arr.data.password : '';

        if(arr.data.account == 'admin') {
            w = 1;
            r = 1;
        }

        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.db1;
        res.db.connect();

        let query = "update ??.?? set `write_privilege` = ? , `read_privilege` = ? " +
            (pass.length > 0 ? " , `user_password` = ? " : "") + " where `account` = ? ";
        let param = [config.db.db1, 'userlist', w.toString(), r.toString()];
        if (pass.length > 0) param.push(pass);
        param.push(arr.data.account);

        res.db.query(query, param, (err, row) => {
            if (err) return n('ERR0021');
            let data = {};
            data.record = [];
            res.api_res = data;
            return n();
        });
    })
    .post('/adduser', (req, res, n) => {
        let arr = req.body;
        if (!tool.checkPermission(req)) return n('ERR9000');
        if (!arr.data) return n('ERR0000');
        if (!arr.data.account) return n('ERR0016');
        if (!arr.data.password) return n('ERR0017');

        let w = arr.data.write_privilege && arr.data.write_privilege == '1' ? 1 : 0;
        let r = arr.data.read_privilege && arr.data.read_privilege == '1' ? 1 : 0;

        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.db1;
        res.db.connect();

        let query = "insert into ??.?? (`account`,`user_password`,`write_privilege`,`read_privilege`,`user_add_date`) values (?,?,?,?,unix_timestamp())";
        let param = [config.db.db1, 'userlist', arr.data.account, arr.data.password, w.toString(), r.toString()];

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

            let data = {};
            data.record = [];
            res.api_res = data;
            return n();
        });
    })
    .post('/dashboard', (req, res, n) => {
        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.db1;
        res.db.connect();

        let data = {
            record: [],
            rt: {}
        };

        data.rt['time'] = [{
            time: Date.now()
        }];

        res.api_res = data;

        let pros = [];
        pros.push(new Promise((resolve, reject) => {
            fs.exists(config.cmdpath.sysinfo, exists => {
                if (!exists) return resolve({ data: [], key: 'sysinfo' });
                fs.readFile(config.cmdpath.sysinfo, (err, d) => {
                    if (err) return resolve({ data: [], key: 'sysinfo' });
                    let s = d.toString();
                    let tmp = s.split(/\n/);
                    for (let i in tmp) {
                        if (!tmp[i].trim()) continue;
                        let tt = tmp[i].split(' ');
                        if (tt.length > 1 && /^ip$/i.test(tt[0])) {
                            return resolve({ data: [{ ip: tt[1] }], key: 'sysinfo' });
                        }
                    }
                });
            });
        }));

        pros.push(new Promise((resolve, reject) => {
            fs.exists(config.cmdpath.version, exists => {
                if (!exists) return resolve({ data: [], key: 'version' });
                fs.readFile(config.cmdpath.version, (err, d) => {
                    if (err) return resolve({ data: [], key: 'version' });
                    return resolve({ data: [{ version: d.toString().replace(/\n/, '') }], key: 'version' });
                });
            });
        }));

        if (config.permission.dio) {
            pros.push(new Promise((resolve, reject) => {
                let q = "select `diname`, `diid`, `diuid` from ??.?? ";
                let p = [config.db.db1, 'dilist'];
                res.db.query(q, p, (err, row) => {
                    if (err) return resolve({ data: [], key: 'di' });
                    let c = row.length;
                    let td = [];
                    ! function chkdi(json) {
                        if (!json) return;
                        exec(`ditchk ${json.diid.replace(/^di([0-9]+)$/, '$1')}`, (err, sout, serr) => {
                            if (err) {
                                chkdi(row.pop());
                                if (!--c) return resolve({ data: td, key: 'di' });
                                return;
                            }
                            if (sout == 1) td.push(json);
                            chkdi(row.pop());
                            if (!--c) return resolve({ data: td, key: 'di' });
                            return;
                        });
                    }(row.pop());
                });
            }));
        }

        if (config.permission.leone) {
            pros.push(new Promise((resolve, reject) => {
                tool.getLeoneRT(rts => {
                    let ips = []
                    for (let i in rts) {
                        if (rts[i].mode == '9999') {
                            ips.push(rts[i].ip);
                        }
                    }
                    let q = "select * from ??.?? where `leoneip` in (?) order by `leonelistuid` desc ";
                    let p = [config.db.db1, 'leonelist', ips];
                    res.db.query(q, p, (err, row) => {
                        if (err) return resolve({ data: [], key: 'leone' });
                        return resolve({ data: row, key: 'leone' });
                    });
                });
            }));
        }

        Promise.all(pros)
            .then(r => {
                for (let i in r) {
                    if (r[i].key == 'di') {
                        data.rt.di = r[i].data;
                    } else if (r[i].key == 'leone') {
                        data.rt.leone = r[i].data;
                    } else if (r[i].key == 'sysinfo') {
                        data.rt.ip = r[i].data;
                    } else if (r[i].key == 'version') {
                        data.rt.version = r[i].data;
                    }
                }
                return n();
            })
            .catch(e => {
                return n();
            });
    })
    .post('/getselectlist', (req, res, n) => {
        let arr = req.body;
        if (!arr.data) return n('ERR0000');
        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.db1;
        res.db.connect();

        res.api_res = {
            record: []
        };

        let pro = null;
        let q, p;
        switch (arr.data.type) {
            case 'do':
                q = "select `doname` as name, `douid` as id from ??.??";
                p = [config.db.db1, 'dolist'];
                pro = tool.promiseQuery(res, q, p, '');
                break;
            case 'di':
                q = "select `diname` as name, `diuid` as id from ??.??";
                p = [config.db.db1, 'dilist'];
                pro = tool.promiseQuery(res, q, p, '');
                break;
            case 'leone':
                q = "select `leonename` as name, `leonelistuid` as id from ??.??";
                p = [config.db.db1, 'leonelist'];
                pro = tool.promiseQuery(res, q, p, '');
                break;
            case 'iogroup':
                q = "select `iogroupname` as name, `iogroupuid` as id from ??.??";
                p = [config.db.db1, 'iogroup'];
                pro = tool.promiseQuery(res, q, p, '');
                break;
            default:
                return n();
        }

        pro.then(r => {
            if('data' in r) {
                res.api_res.record = tool.checkArray(r.data);
            }
            return n();
        }).catch(e => {
            return n();
        })
    })
    .all('*', rt.send);

module.exports = router;