export default class WsMultipleInputController {
  static $inject = ['$window', '$timeout'];

  constructor($window, $timeout) {
    this.$window = $window;
    this.$timeout = $timeout;
  }

  $onInit() {
    this.inputCount = parseInt(this.numberOfInputs, 10);
    this.inputs = this.inputs || [];
  }

  $postLink() {
    this.$timeout(() => {
      if (this.autoFocus) {
        angular.element.find('.ws-multiple-input')[0].focus();
      }
    }, 0);
  }

  $onChanges(changesObj) {
    if (changesObj.value && angular.isString(changesObj.value.currentValue)) {
      // Update internal representation when value is updated on the parent
      const newInputsValue = changesObj.value.currentValue.split('').map(Number);
      this.inputs = newInputsValue;

      // Focus on next element
      const positionToFocus = newInputsValue.length;
      if (angular.isDefined(angular.element.find('.ws-multiple-input')[positionToFocus])) {
        angular.element.find('.ws-multiple-input')[positionToFocus].focus();
      }
    }
  }

  range = n => new Array(n);

  onKeyPress = ($event) => {
    if (this.isReadonly) {
      return Promise.resolve();
    }

    return this.$timeout(() => {
      // When maximum length is reached for current input, not counting movements
      if ($event.target.value.length === $event.target.maxLength && !($event.key === 'ArrowLeft' || $event.key === 'ArrowRight')) {
        const inputs = this.inputs;
        const populated = inputs.filter(input => (angular.isString(input) && input.length > 0)
                                                 || angular.isNumber(input));
        // If all inputs have been populated, calls onCompleted
        // Otherwise, move to next input
        if (populated.length === this.inputCount) {
          const finalInput = inputs.join('');
          this.onCompleted({ result: finalInput });
        } else if ($event.target.nextElementSibling !== null) {
          $event.target.nextElementSibling.focus();
        }
      }
    }, 25);
  };

  onKeyDown = ($event) => {
    if (this.isReadonly) {
      return;
    }

    // Browsers have a hard time limiting input for <input type="number">
    if (($event.keyCode === 32 || $event.keyCode > 57) &&
        !$event.altKey && !$event.ctrlKey && !$event.metaKey) {
      $event.preventDefault();
    }

    // When trying to delete from an empty input, delete from the previous one
    if (($event.target.value.length === 0) && ($event.key === 'Backspace')) {
      if ($event.target.previousElementSibling !== null) {
        $event.preventDefault();
        $event.target.previousElementSibling.focus();
        $event.target.previousElementSibling.value = '';
      }
    }
    if ($event.key === 'ArrowLeft') {
      if ($event.target.previousElementSibling !== null) {
        $event.preventDefault();
        $event.target.previousElementSibling.focus();
      }
    }
    if ($event.key === 'ArrowRight') {
      if ($event.target.nextElementSibling !== null) {
        $event.preventDefault();
        $event.target.nextElementSibling.focus();
      }
    }
  };

  onPaste = ($event) => {
    $event.preventDefault();

    // jQuery's doesn't expose Clipboard API
    const clipboardData = ($event.originalEvent.clipboardData || this.$window.clipboardData);
    const pasteData = clipboardData.getData('Text');

    const splitData = pasteData.slice(0, this.inputCount).split('');
    this.inputs = splitData;

    // Because the paste filled all inputs we fire onCompleted
    if (splitData.length === this.inputCount) {
      this.onCompleted({ result: this.inputs.join('') });
    }
  };
}
