"use strict";

let http = require('http');
let net = require('net');
let os = require('os');
let zlib = require('zlib');
let machine = require('node-machine-id');

let SocClient = function(master) {
    "use strict";

    let self = this;

    let RECONNECT_INTERVAL = 5000;

    let APP_VERSION_NAME = "3.0";
    let APP_VERSION_CODE = 30;

    let STATUS_CONNECTING = 'connecting';
    let STATUS_CONNECTED = 'connected';
    let STATUS_DISCONNECTED = 'disconnected';
    let STATUS_RECONNECTING = 'reconnecting';

    let client = null;
    let status = null;
    let timer = null;
    let connecting_count = 0;
    let reconnecting_count = 0;

    let dataCompleted = '';
    let i,json,json2,ismulti;
    this.connect = function(fromTimmer) { console.log("SocClient.connect() port:"+master.getPort());

        if (!fromTimmer && (status === STATUS_CONNECTED || status === STATUS_CONNECTING || status === STATUS_RECONNECTING)) {
            return;
        }

        clearTimeout(timer);
        destroy();
        status = STATUS_CONNECTING;
        client = net.connect(master.getPort(), master.getIp(), function() { console.log('connected!');
            status = STATUS_CONNECTED;
            connecting_count = 0;
            reconnecting_count = 0;

            self.send({
                "action": "APP_CONNECT",
                "serial": self.getDeviceId(),
                "tel_version": 'PC',
                "marca": os.platform(),
                "modelo": os.arch(),
                "mac": machine.machineIdSync({original: true}),
                "app_version": APP_VERSION_NAME
            });
        });

        client.on('data', function(data) {
            //data = decompress(data);
            data = data.toString().trim(); console.log("soc_recv: " + data);

            if (data.slice(-1) === '|') {
                dataCompleted += data.slice(0,-1);
            }
            else {
                dataCompleted += data;
                return;
            }

            data = dataCompleted;
            dataCompleted = '';
            ismulti = false;

            if (data.indexOf('|') >= 0) {
                ismulti = true;
                json2 = [];
                let datas = data.split('|');
                for (i=0; i<datas.length; i++) {
                    json2.push(JSON.parse(datas[i]));
                }
                //logger.w(data, 'PACKET_MULTIPLE', serial);
            }
            else {
                json = JSON.parse(data);
            }

            if (ismulti) {
                for (i=0; i<json2.length; i++) {
                    json = json2[i];
                    master.onMessage(json);
                }
            }
            else {
                master.onMessage(json);
            }
        });

        client.on('error', function(err){
            console.log("Error: "+err.message);
        });

        client.on('end', function() {
            console.log('client.end()');
        });

        client.on('close', function() { console.log('soc_on_close status:' + status);

            if (status == STATUS_CONNECTED) {
                console.log('disconnected from server (close)');
                status = STATUS_CONNECTING;
                master.onConnectionLost();
            }
            else if (status == STATUS_RECONNECTING) {
                connecting_count++;
                console.log("intento1 de conexion fallido # "+connecting_count);
            }
            else if (status == STATUS_CONNECTING) {
                reconnecting_count++;
                console.log("intento2 de reconexion fallido # "+reconnecting_count);
            }

            timer = setTimeout(function() {self.connect(true);}, RECONNECT_INTERVAL);
        });
    }

    this.isConnected = function() {
        return status === STATUS_CONNECTED;
    }

    this.send = function(data) { console.log("SocClient.send(): " + JSON.stringify(data));
        //client.write(compress(JSON.stringify(data) + "|"));
        data["serial"] = self.getDeviceId();
        client.write(JSON.stringify(data) + "|");
    }

    this.close = function() {
        destroy();
    }

    this.getDeviceId = function() {
        return machine.machineIdSync().substr(0,20);
    }

    let compress = function(data) {
        return zlib.deflateSync(data);
    }

    let decompress = function(data) {
        return zlib.inflateSync(data);
    }

    let destroy = function() { //console.log("SocClient.destroy()");
        if (client == null) { return; }
        client.destroy();
        client = null;
    }

    let do_connect = function() {
        connect();
    }

    let get_status = function() {
        return status;
    }




    this.testConnect = async function(ip) {
        ip = int2ip(ip); console.log("SocClient.testConnec() ip:"+ip);

        return new Promise(function(resolve, reject) {
            let res = net.connect(master.server_port, ip, function() {
                resolve(ip);
            });

            res.on('error', function(err) {
                reject('error');
            });
        });

        console.log("bbb");
    }

    this.getVersion = function() {
        return APP_VERSION_NAME;
    }

    let int2ip = function(ipInt) {
        return ( (ipInt>>>24) +'.' + (ipInt>>16 & 255) +'.' + (ipInt>>8 & 255) +'.' + (ipInt & 255) );
    }
}

module.exports = SocClient;