/**
 * Created by Zheng Li on 2015/8/29.
 */


var x = x || {};
x.hub = x.hub || {};
x.hub.port = null; //callback server port;
x.hub.sigterm = false;

x.hub.sysConsole = {
    _console: console,
    load: require,
    loopcheck: 0,
    loopline: -1,
    loopProtect: function(info){
        if (info && info.line) {
            if (info.line != x.hub.sysConsole.loopline) {
                x.hub.sysConsole.loopline = info.line;
                x.hub.sysConsole.loopcheck = 0;
            } else {
                x.hub.sysConsole.loopcheck++;
            }
        } else {
            x.hub.sysConsole.loopcheck++;
        }
        if (x.hub.sysConsole.loopcheck > 10000) {
            x.hub.sysConsole.log("There may be an infinite loop at line: " +
                (x.hub.sysConsole.loopline - 207));
            process.exit();
        }
    },
    log: function() {
        var args = Array.prototype.slice.call(arguments);
        this._console.log.apply(this._console, args);

        if (process.platform === 'win32') {
            var self = this;
            process.send({ log: args }, function(err) {
                self._console.log("ipc log finish", err);
            });
        }
    },
    error: function() {
        var args = Array.prototype.slice.call(arguments);
        this._console.error.apply(this._console, args);

        if (process.platform === 'win32') {
            var self = this;
            process.send({ error: args }, function(err) {
                self._console.error("ipc error finish", err);
            });
        }
    }
};

var func = function(){

    var require = function(name) {
        switch (name) {
            case 'child_process':
            case 'vm':
                return;
        }
        //x.hub.sysConsole.log("load", arguments);
        return x.hub.sysConsole.load(name);
    };
    var console = {
        log: function() {
            var args = Array.prototype.slice.call(arguments);
            return x.hub.sysConsole.log.apply(x.hub.sysConsole, args);
        },
        error: function() {
            var args = Array.prototype.slice.call(arguments);

            for (var i = 0; i < args.length; i++) {
                if (args[i] instanceof Error) {
                    args[i] = args[i].message;
                }
            }

            x.hub.sysConsole.error.apply(x.hub.sysConsole, args);
        },
        debug: function() {
            var args = Array.prototype.slice.call(arguments);
            x.hub.sysConsole.log.apply(x.hub.sysConsole, args);
        },
        info: function() {
            var args = Array.prototype.slice.call(arguments);
            x.hub.sysConsole.log.apply(x.hub.sysConsole, args);
        },
        warn: function() {
            var args = Array.prototype.slice.call(arguments);
            x.hub.sysConsole.log.apply(x.hub.sysConsole, args);
        }
    };

    var protect = function(info){
        x.hub.sysConsole.loopProtect(info);
    };

    var executeDeviceCommand = function(roomName, deviceName, command, callback) {
        var data = {
            "func": "executeCommand",
            "device": {
                device:deviceName,
                room:roomName
            },
            "command":command
        };
        _doPostRequest(data, callback);
        //jsonrpc.doRPC("executeCommand", data, callback);
    };

    var getDeviceStatus = function(roomName, deviceName, status, callback) {
        var data = {
            "func": "getStatus",
            "device": {
                device:deviceName,
                room:roomName
            },
            "status":status
        };
        _doPostRequest(data, function(err, result){
            if (err) {
                callback && callback(err);
                return;
            }
            callback && callback(null, result?result.value:null);
        });

//        jsonrpc.doRPC("getStatus", data, function(err, result){
//            if (err) {
//                callback && callback(err);
//                return;
//            }
//            callback && callback(null, result?result.value:null);
//        });
    };

    var executeMacro = function(groupName, macroName, callback) {
        var data = {
            "func": "executeMacro",
            "groupName": groupName,
            "macroName":macroName
        };
        _doPostRequest(data, callback);
//        jsonrpc.doRPC("executeMacro", data, callback);
    };

    var _doPostRequest  = function(data, callback){
        var http = require("http");
        var options = {
            hostname: "127.0.0.1",
            port:x.hub.port,
            method:"POST",
            path:"/xhub/script/callback",
            headers:{
                "Content-Type": "application/json"
            }
        };
        //console.log("options",options);
        var cb = callback;
        var req = http.request(options, function(res){
            //console.log("STATUS:"+res.statusCode);
            //console.log("HEADERS:"+JSON.stringify(res.headers));
            res.setEncoding('utf8');
            var body = "";
            res.on('data', function(chunk){
                body += chunk;
            });
            res.on('end',function() {
                //console.log('body:'+body);
                if (res.statusCode != 200) {
                    cb && cb(new Error("system request fail"));
                } else {
                    try {
                        var data = JSON.parse(body);
                        if (data.status == "success") {
                            cb && cb(null, data.data);
                        } else {
                            cb && cb(new Error(data.message));
                        }
                    } catch (e) {
                        cb && cb(new Error("system request fail: "+ e.message));
                    }

                }
                cb = null;
            });
        });
        req.setTimeout(10000, function(){
            cb && cb (new Error("system request timeout"));
            cb = null;
        });
        req.on("error", function(err){
            cb && cb(err);
            cb = null;
        });
        req.write(JSON.stringify(data));
        req.end();
    };

    var global, process, _filename, __dirname, module, exports, eval;

    var js = function() {
        var load,deviceManager;
        //%CODE
    };

    try {
        js.call(js);
    } catch (e) {
        console.error(e);
    }
};

var runner = {
    run: function() {
        func();
    }
};

var protect = function(info){
    x.hub.sysConsole.loopProtect(info);
};

var jsonrpc = {
    _rpcID: 0,
    _calls: [],
    doRPC: function(method, params, callback){
        this._rpcID++;
        var call = {
            jsonrpc: "2.0",
            method: method,
            params: params,
            id: this._rpcID
        }
        process.send(call);
        call.callback = callback;
        this._calls.push(call);
    },
    //result example
    //{"jsonrpc": "2.0", "result": 19, "id": 1}
    //{"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "1"}
    doRPCCallback: function(response) {
        if (!response || !response.id) return;
        var i=-1;
        var call = null;
        for (i=0;i<this._calls.length;i++) {
            if (this._calls[i] && this._calls[i].id == response.id) {
                call = this._calls[i];
                break;
            }
        }
        if (!call) return;
        this._calls.splice(i, 1);
        var err = null;
        var ret = null;
        if (response.error) {
            err = new Error(response.error.message?response.error.message:'unknown error');
            err.code = response.error.code;
        }
        if (response.result) {
            ret = response.result;
        }
        if (call.callback) {
            call.callback(err, ret);
        }
    }
}

process.on('SIGTERM', function() {
    console.log('Got SIGTERM.  Process exit.');
    x.hub.sigterm = true;
//    process.nextTick(function() {
//        if (x.hub.sigterm) {
//            process.exit();
//        }
//    });
    process.exit();
});

/*
process.on('message', function (m) {
    console.log('CHILD got message:', m);
    if (m && m.jsonrpc == "2.0") {
        jsonrpc.doRPCCallback(m)
    }
});
*/

process.argv.forEach(function(val, index, array) {
    //console.log(index + ': ' + val);
});
x.hub.port = process.argv[2];
runner.run();