var Clay = require('pebble-clay');
var clayConfig = require('./config');
var clay = new Clay(clayConfig);
const jsSHA = require('./sha');

var messageKeys = require('message_keys');

var sid;
var status;
var retry;
retry = 0;


function dec2hex(s) {
    return (s < 15.5 ? '0' : '') + Math.round(s).toString(16);
}

function hex2dec(s) {
    return parseInt(s, 16);
}

function base32tohex(base32) {
    var base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
    var bits = "";
    var hex = "";

    for (var i = 0; i < base32.length; i++) {
        var val = base32chars.indexOf(base32.charAt(i).toUpperCase());
        bits += leftpad(val.toString(2), 5, '0');
    }
    //console.log('-- bits : ' + bits)

    for (var i = 0; i + 4 <= bits.length; i += 4) {
        var chunk = bits.substring(i, i + 4);
        hex = hex + parseInt(chunk, 2).toString(16);
    }
    return hex;

}

function leftpad(str, len, pad) {
    if (len + 1 >= str.length) {
        str = Array(len + 1 - str.length).join(pad) + str;
    }
    return str;
}

function getOtp() {
    key = base32tohex(JSON.parse(localStorage.getItem('clay-settings')).OTP_seed)
        //console.log('-- seed:' + JSON.parse(localStorage.getItem('clay-settings')).OTP_seed)
        //console.log('-- key:' + key)
    var epoch = Math.round(new Date().getTime() / 1000.0);
    var time = leftpad(dec2hex(Math.floor(epoch / 30)), 16, '0');
    // updated for jsSHA v2.0.0 - http://caligatio.github.io/jsSHA/
    var shaObj = new jsSHA("SHA-1", "HEX");
    shaObj.setHMACKey(key, "HEX");
    shaObj.update(time);
    var hmac = shaObj.getHMAC("HEX");
    //console.log('-- hmac:' + hmac)
    var offset = hex2dec(hmac.substring(hmac.length - 1));
    //console.log('--offset:' + offset)
    var otp = (hex2dec(hmac.substring(offset * 2, offset * 2 + 8)) & hex2dec('7fffffff')) + '';
    otp = (otp).substring(otp.length - 6, otp.length);
    return otp
}

function xhr_to_syno(method, url_path, onload_function, max_retry) {
    console.log('------xhr start')
    status = "";
    if (JSON.parse(localStorage.getItem('clay-settings')).server) {
        var server = JSON.parse(localStorage.getItem('clay-settings')).server
        url = server + url_path;
        var xhr = new XMLHttpRequest();
        xhr.timeout = 60000; // time in milliseconds

        xhr.open(method, url, true);
        console.log('------xhr opened')
        xhr.onload = function() {
            console.log('------xhr onload')
            if (xhr.readyState === 4) {
                retry = 0;
                console.log('------xhr request returned');
                if (xhr.status == 200) {
                    onload_function(xhr);
                    return true;
                } else {
                    console.log('------xhr request returned error code ' + xhr.status);
                    message = "Error (XHR" + xhr.status + ")";
                    // Build message
                    var dict = {
                        'status': message,
                    };

                    // Send the message
                    Pebble.sendAppMessage(dict, function(e) {
                        console.log('sent');
                    }, function() {
                        console.log('failed');
                    });
                    return false;
                }
            }
        };

        xhr.ontimeout = function(e) {
            retry++;
            if (retry < max_retry) {
                console.log('------xhr timed out retrying another time ');
                //send back "timeout" to watch
                message = "Time out (" + retry + "), retrying...";

                // Build message
                var dict = {
                    'status': message,
                };

                // Send the message
                Pebble.sendAppMessage(dict, function(e) {
                    console.log('sent');
                }, function() {
                    console.log('failed');
                });

                setTimeout(function() { xhr_to_syno(method, url_path, onload_function, max_retry) }, 60000 * retry);
            } else {
                console.log('------xhr timed out ' + retry + ' times');
                //send back "timeout" to watch
                message = "Time out " + retry + " times, verify settings and connectivity";

                // Build message
                var dict = {
                    'status': message,
                };

                // Send the message
                Pebble.sendAppMessage(dict, function(e) {
                    console.log('sent');
                }, function() {
                    console.log('failed');
                });
                return false;
            }
        };
        xhr.send(null);

    } else {
        Pebble.showSimpleNotificationOnPebble("DSCam H-S", "You need to set your Synology account and server.");
    }

}


function authenticate() {
    var response;
    sid = "";
    console.log('---- authenticate');
    if (JSON.parse(localStorage.getItem('clay-settings')).username && JSON.parse(localStorage.getItem('clay-settings')).password) {
        var username = JSON.parse(localStorage.getItem('clay-settings')).username;
        var password = JSON.parse(localStorage.getItem('clay-settings')).password;
        console.log('-- username:' + username);
        console.log('-- password:' + password.substring(0, 1) + '...');
        var url_path = "/webapi/auth.cgi?api=SYNO.API.Auth&method=Login&version=6&account=" + username + "&passwd=" + password + "&session=SurveillanceStation&format=sid";
        if (JSON.parse(localStorage.getItem('clay-settings')).OTP_enabled) {
            var otp_code = getOtp()
            console.log('-- otp_code is :' + otp_code)
            url_path = url_path + "&otp_code=" + otp_code
        }
        var method = "GET";
        onload_function = function(xhr) {
            response = JSON.parse(xhr.responseText);
            if (response.success == true) {
                sid = response.data.sid;
                console.log('------Authentication succeeded');
                if (sid != "") {
                    message = "Welcome to Syno Cam Switch ! ready & authenticated";
                    // Build message
                    var dict = {
                        'auth': message,
                    };
                    // Send the message
                    Pebble.sendAppMessage(dict, function(e) {
                        console.log('sent');
                    }, function() {
                        console.log('failed');
                    });
                    get_status();
                } else {
                    console.log('------Unexpected error : authentication is OK but no SID retrieved');
                    message = "Auth error, no SID";
                    // Build message
                    var dict = {
                        'auth': message,
                    };
                    // Send the message
                    Pebble.sendAppMessage(dict, function(e) {
                        console.log('sent');
                    }, function() {
                        console.log('failed');
                    });
                }
            } else {
                console.log('------Authentication failed : ' + JSON.stringify(response));
                message = "Authentication failed";
                // Build message
                var dict = {
                    'auth': message,
                };
                // Send the message
                Pebble.sendAppMessage(dict, function(e) {
                    console.log('sent');
                }, function() {
                    console.log('failed');
                });
            }
        };
        max_retry = 10;
        xhr_to_syno(method, url_path, onload_function, max_retry);
    } else {
        console.log("--- failed to get settings");
        Pebble.showSimpleNotificationOnPebble("DSCam H-S", "You need to set your Synology account and server.");
    }


}


function get_status() {
    var response;

    if (sid != "") {
        status = "";
        console.log('---- get_status');

        var url_path = "/webapi/entry.cgi?api=SYNO.SurveillanceStation.HomeMode&version=1&method=GetInfo&_sid=" + sid;
        var method = "GET";

        onload_function = function(xhr) {
            response = JSON.parse(xhr.responseText);
            if (response.success == true) {
                status = response.data.on;
                var message;
                switch (status) {
                    case true:
                        message = "Home mode is ON (camera is off)";
                        break;
                    case false:
                        message = "Home mode is OFF (camera is on)";
                        break;
                    default:
                        message = "something happened, try again ! (IMPOSSIBLE)";
                }
            } else {
                message = "something happened, try again ! (G200)";
            }
            // Build message
            var dict = {
                'status': message,
            };

            // Send the message
            Pebble.sendAppMessage(dict, function(e) {
                console.log('sent');
            }, function() {
                console.log('failed');
            });
        }

        max_retry = 10;
        xhr_to_syno(method, url_path, onload_function, max_retry);

    } else {
        authenticate();
        get_status();
    }

}


function switch_home(bool) {
    var response;
    console.log('---- authenticate');
    if (sid != "") {
        console.log('---- switching home mode to ' + bool);
        url_path = "/webapi/entry.cgi?api=SYNO.SurveillanceStation.HomeMode&version=1&method=Switch&on=" + bool + "&_sid=" + sid;
        method = "GET"
        onload_switch_function = function(xhr) {
            response = JSON.parse(xhr.responseText);
            if (response.success == true) {
                switch (bool) {
                    case true:
                        message = "Home mode is ON (camera is off)";
                        break;
                    case false:
                        message = "Home mode is OFF (camera is on)";
                        break;
                    default:
                        message = "something happened, try again ! (IMPOSSIBLE)";
                }
            } else {
                message = "something happened, try again ! (S200)";
            }
            // Build message
            dict = {
                'status': message,
            };

            // Send the message
            Pebble.sendAppMessage(dict, function(e) {
                console.log('sent');
            }, function() {
                console.log('failed');
            });
        }
        max_retry = 10;
        xhr_to_syno(method, url_path, onload_switch_function, max_retry);


    } else {
        authenticate();
        switch_home(bool);
    }

}

// Get JS readiness events
Pebble.addEventListener('ready', function(e) {
    console.log("---- local storage:");
    console.log("user " + JSON.parse(localStorage.getItem('clay-settings')).username);
    console.log('PebbleKit JS is ready');
    // Update Watch on this
    Pebble.sendAppMessage({ 'JSReady': 1 });
});

// Get AppMessage events
Pebble.addEventListener('appmessage', function(e) {
    // Get the dictionary from the message
    var dict = e.payload;
    console.log(dict[0].toString());
    switch (dict[0]) {
        case 'auth':
            authenticate();
            break;
        case 'get':
            get_status();
            break;
        case 'home_on':
            switch_home(true);
            break;
        case 'home_off':
            switch_home(false);
            break;
        default:
            console.log('Sorry. I don\'t understand your request :' + dict[0]);
    }

});