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 = 1;


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.substr(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.substr(offset * 2, 8)) & hex2dec('7fffffff')) + '';
  otp = (otp).substr(otp.length - 6, 6);
  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 = 6000; // time in milliseconds

    xhr.open(method, url, true);
    console.log('------xhr opened')
    xhr.onload = function () {
      console.log('------xhr onload')
      if (xhr.readyState === 4) {
        retry = 1;
        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, retrying...";

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

        // Send the message
        Pebble.sendAppMessage(dict, function (e) {
          console.log('sent');
        }, function () {
          console.log('failed');
        });
        xhr_to_syno(method, url_path, onload_function, max_retry);
      } else {
        console.log('------xhr timed out ' + retry + ' times');
        //send back "timeout" to watch
        message = "Time out too many 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 timed_switch_home(duration) {
  var response;
  console.log('---- authenticate');
  if (sid != "") {
    var epoch = Math.round(new Date().getTime() / 1000.0);
    var start_ts = epoch + 10
    var end_ts = duration + start_ts
    console.log('---- switching home mode for ' + duration + 'seconds');
    url_path = "/webapi/entry.cgi?api=SYNO.SurveillanceStation.HomeMode&version=1&method=SaveOneTimeSwitch&onetime_enable_on=true&onetime_disable_on=true&onetime_enable_time=" + start_ts + "&onetime_disable_time=" + end_ts + "&_sid=" + sid;
    method = "GET"
    onload_switch_function = function (xhr) {
      response = JSON.parse(xhr.responseText);
      if (response.success == true) {
          message = "Home mode is ON for "+duration+" seconds";
      }else{
        message = "something happened, try again ! (S200)";
      }
      // Build message
      dict = {
        'status': message,
      };

      // Send the message Home mode is ON for 900 seconds
      Pebble.sendAppMessage(dict, function (e) {
        console.log('sent \"'+message+'\"');
      }, function () {
        console.log('failed');
      });
    }
    max_retry = 10;
    xhr_to_syno(method, url_path, onload_switch_function, max_retry);


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

}

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);
      timed_switch_home(15*60)
      break;
    case 'home_off':
      switch_home(false);
      break;
    default:
      console.log('Sorry. I don\'t understand your request :' + dict[0]);
  }

});