"use strict";

var Service	  = require('./service.js');
var console	  = require('gifer-console');
var MCConnect = require('./mcconnect.js');
var CMD       = MCConnect.CMD;

var inc        = 0;
var parseFunc  = {};
var CR         = "\r";
var nt         = "";

/**
 * @return {string}
 */
function SessionID_Generator (){
    inc ++;

    return inc + Service.RandomHash(50);
}

function createContext(id, cmd, data, pwd, srvPwd) {
    return {
        login      : data.UIN,
        pass       : pwd, // originPass,
        Pass       : data.Pass,

        Secured              : data.Secured,
        Gender               : data.Gender,
        Email                : data.Email,
        SecretQuestionNumber : data.SecretN || 0,
        SecretAnswer         : data.SecretA || 1,
        ClientType           : MCConnect.getClientType(),
        Style                : data.Style,
        NodeUserAgent        : data.UserAgent,
        NodeReferral         : data.Referral,
        // State                : data.State,

        ServPass             : srvPwd, // originSrvPass,

        Token                : "",       // виставляє резолв у sc_hello; без поля білдер шле {"Token": undefined}
        // «запам'ятати мене»: читалось локально (:67) і в контекст не потрапляло. Нормалізуємо до
        // булевого — по транспорту значення може приїхати рядком
        RM                   : !!data.RM && data.RM !== 'false',

        PingDelay  : data.PingDelay || 25,
        host       : data.Host,
        port       : data.Port,
        altHost    : data.AltHost || "",
        altPort    : data.AltPort || "",

        //clientIP   : Host, // todo: add my IP
        sessionID  : id,
        authType   : cmd
    }
}

function genPwd(originPass, originSrvPass, gen) {
    var pwd = "";

    if (gen) {
        pwd = CR + ((originPass)    ? Service.Encrypt(nt, originPass || "")    : "") +
              CR + ((originSrvPass) ? Service.Encrypt(nt, originSrvPass || "") : "");
    } else {
        pwd = CR + originPass + CR + (originSrvPass || "");
    }

    return pwd
}

function doLogin(id, data, originPass, originSrvPass, cmd, CallBack){
    const RM = data.RM;

    MCConnect.MakeClientConnection(createContext(id, cmd, data, originPass, originSrvPass));

    if (CallBack){
        CallBack(cmd + CR + id + genPwd(originPass, originSrvPass, RM));
    } else {
        console.err('Not assigned CallBack on CMD:' + cmd);
    }
}

function decodePwd(data) {
    var originPass    = "";
    var originSrvPass = "";

    nt = Service.Base64.decode(MCConnect.getNT());

    try {
        originPass    = data.RM                  ? Service.Decrypt(nt, data.Pass || "")     : (data.Pass || "");
        originSrvPass = data.ServPass && data.RM ? Service.Decrypt(nt, data.ServPass || "") : (data.ServPass || "");
    } catch (e){
        originPass    = data.Pass || "";
        originSrvPass = data.ServPass || "";
    }

    return [originPass, originSrvPass];
}

function _Auth(_data, cmd, CallBack){
    var id   = SessionID_Generator();
    var data = Service.StringToObj(_data);
    var pwds = decodePwd(data);

    doLogin(id, data, pwds[0], pwds[1], cmd, CallBack);
}

parseFunc[CMD.Login]       = function Login(_data, SendDataToWebClient){
    _Auth(_data, CMD.Login, SendDataToWebClient);
};

parseFunc[CMD.Register]    = function Register(_data, SendDataToWebClient){
    _Auth(_data, CMD.Register, SendDataToWebClient);
};

parseFunc[CMD.Ping]        = function Ping(_data, SendDataToWebClient){
    var data = _data.split(CR);
    var sID  = data[0];
    
    MCConnect.SendDataToServer(sID, MCConnect.CMD.cs_ping, null, SendDataToWebClient);
};


function UniversalParser (_CMD, _data, SendDataToWebClient){
    if (parseFunc.hasOwnProperty(_CMD)) {
        parseFunc[_CMD](_data, SendDataToWebClient);
    } else {
        var data = (_data || "").split(CR);
        var sID  = data.shift().toString();

        MCConnect.SendDataToServer(sID, _CMD, data, SendDataToWebClient);
    }
}

exports.UniversalParser = UniversalParser;