'use strict';

angular.module('copayApp.controllers').controller('pinController', function($state, $interval, $stateParams, $ionicHistory, $timeout, $scope, $log, configService, appConfigService) {
  var ATTEMPT_LIMIT = 3;
  var ATTEMPT_LOCK_OUT_TIME = 5 * 60;
  var currentPin;

  $scope.$on("$ionicView.beforeEnter", function(event) {
    currentPin = $scope.confirmPin = '';
    $scope.action = $stateParams.action;
    $scope.match = $scope.error = $scope.disableButtons = false;
    $scope.currentAttempts = 0;
    $scope.appName = appConfigService.name;
  });

  $scope.$on("$ionicView.enter", function(event) {
    configService.whenAvailable(function(config) {
      if (!config.lock) return;
      $scope.bannedUntil = config.lock.bannedUntil || null;
      if ($scope.bannedUntil) {
        var now = Math.floor(Date.now() / 1000);
        if (now < $scope.bannedUntil) {
          $scope.error = $scope.disableButtons = true;
          lockTimeControl($scope.bannedUntil);
        }
      }
    });
  });

  function getSavedMethod() {
    var config = configService.getSync();
    if (config.lock) return config.lock.method;
    return 'none';
  };

  function checkAttempts() {
    $scope.currentAttempts += 1;
    $log.debug('Attempts to unlock:', $scope.currentAttempts);
    if ($scope.currentAttempts === ATTEMPT_LIMIT) {
      $scope.currentAttempts = 0;
      var bannedUntil = Math.floor(Date.now() / 1000) + ATTEMPT_LOCK_OUT_TIME;
      saveFailedAttempt(bannedUntil);
    }
  };

  function lockTimeControl(bannedUntil) {
    setExpirationTime();

    var countDown = $interval(function() {
      setExpirationTime();
    }, 1000);

    function setExpirationTime() {
      var now = Math.floor(Date.now() / 1000);
      if (now > bannedUntil) {
        if (countDown) reset();
      } else {
        $scope.disableButtons = true;
        var totalSecs = bannedUntil - now;
        var m = Math.floor(totalSecs / 60);
        var s = totalSecs % 60;
        $scope.expires = ('0' + m).slice(-2) + ":" + ('0' + s).slice(-2);
      }
    };

    function reset() {
      $scope.expires = $scope.error = $scope.disableButtons = null;
      currentPin = $scope.confirmPin = '';
      $interval.cancel(countDown);
      $timeout(function() {
        $scope.$apply();
      });
      return;
    };
  };

  $scope.getFilledClass = function(limit) {
    return currentPin.length >= limit ? 'filled-' + $scope.appName : null;
  };

  $scope.delete = function() {
    if ($scope.disableButtons) return;
    if (currentPin.length > 0) {
      currentPin = currentPin.substring(0, currentPin.length - 1);
      $scope.error = false;
      $scope.updatePin();
    }
  };

  $scope.isComplete = function() {
    if (currentPin.length < 4) return false;
    else return true;
  };

  $scope.updatePin = function(value) {
    if ($scope.disableButtons) return;
    $scope.error = false;
    if (value && !$scope.isComplete()) {
      currentPin = currentPin + value;
      $timeout(function() {
        $scope.$apply();
      });
    }
    $scope.save();
  };

  function isMatch(pin) {
    var config = configService.getSync();
    return config.lock.value == pin;
  };

  $scope.save = function() {
    if (!$scope.isComplete()) return;
    var savedMethod = getSavedMethod();

    switch ($scope.action) {
      case 'setup':
        applyAndCheckPin();
        break;
      case 'disable':
        if (isMatch(currentPin)) {
          deletePin();
        } else {
          showError();
          checkAttempts();
        }
        break;
      case 'check':
        if (isMatch(currentPin)) return $scope.close();
        showError();
        checkAttempts();
        break;
    }
  };

  function showError() {
    $timeout(function() {
      $scope.confirmPin = currentPin = '';
      $scope.error = true;
    }, 200);

    $timeout(function() {
      $scope.$apply();
    });
  };

  function applyAndCheckPin() {
    if (!$scope.confirmPin) {
      $timeout(function() {
        $scope.confirmPin = currentPin;
        currentPin = '';
      }, 200);
    } else {
      if ($scope.confirmPin == currentPin)
        savePin($scope.confirmPin);
      else {
        $scope.confirmPin = currentPin = '';
        $scope.error = true;
      }
    }
    $timeout(function() {
      $scope.$apply();
    });
  };

  function deletePin() {
    var opts = {
      lock: {
        method: 'none',
        value: null,
        bannedUntil: null,
      }
    };

    configService.set(opts, function(err) {
      if (err) $log.debug(err);
      $scope.close();
    });
  };

  function savePin(value) {
    var opts = {
      lock: {
        method: 'pin',
        value: value,
        bannedUntil: null,
      }
    };

    configService.set(opts, function(err) {
      if (err) $log.debug(err);
      $scope.close();
    });
  };

  function saveFailedAttempt(bannedUntil) {
    var opts = {
      lock: {
        bannedUntil: bannedUntil,
      }
    };

    configService.set(opts, function(err) {
      if (err) $log.debug(err);
      lockTimeControl(bannedUntil);
    });
  };

  $scope.close = function(delay) {
    $timeout(function() {
      var shouldReturn = $ionicHistory.viewHistory().backView && $ionicHistory.viewHistory().backView.stateName != 'starting';

      if (shouldReturn)
        $ionicHistory.goBack()
      else
        $state.go('tabs.home');
    }, delay || 1);
  };
});
