import EventManager from './EventManager';
import TaskRunner from './TaskRunner';

function isEvent(event) {
  return Boolean(event && event.target);
}

function isKeyboardEvent(event) {
  if (event && event.type === 'keydown') {
    event.preventDefault();
    return true;
  }

  return false;
}

function keep(fn, props, e) {
  var _this = this;

  var getStepGenerator = props.getStepGenerator,
      _props$run = props.run,
      run = _props$run === void 0 ? fn : _props$run,
      validator = props.validator,
      enabled = props.enabled,
      _props$delay = props.delay,
      delay = _props$delay === void 0 ? 200 : _props$delay,
      _props$interval = props.interval,
      interval = _props$interval === void 0 ? 40 : _props$interval;

  if (!enabled || enabled.call(this) && (!isKeyboardEvent(e) || !e.repeat)) {
    var generator = getStepGenerator.call(this);
    var firstValue = generator.next().value;
    var currentValue = firstValue;

    if (isEvent(e)) {
      var currentTarget = e.currentTarget,
          type = e.type;
      var delayer = new TaskRunner();
      var keeper = new TaskRunner();
      var event = new EventManager(currentTarget);

      var stopFn = function stopFn() {
        if (delayer.isRunning) {
          delayer.cancel();
          fn.call(_this, firstValue);
        }

        if (keeper.isRunning) {
          keeper.cancel();
          fn.call(_this, currentValue);
        }

        event.clear();
      };

      var delayFn = function delayFn() {
        keeper.run(interval, function () {
          if (validator.call(_this, currentTarget) === false) {
            stopFn();
          } else {
            currentValue = generator.next().value;
            run.call(_this, currentValue);
          }
        });
      };

      delayer.delay(delay, delayFn);

      if (type === 'keydown') {
        event.addEventListener('keyup', stopFn).addEventListener('blur', stopFn);
      } else {
        event.addEventListener('mouseleave', stopFn).addEventListener('mouseup', stopFn);
      }

      run.call(this, firstValue);
    } else {
      fn.call(this, firstValue);
    }
  }
}

export default function keepRunning(props) {
  return function (target, _key, descriptor) {
    var constructor = target.constructor;
    var fn = descriptor.value;
    return {
      enumerable: false,
      configurable: true,
      get: function get() {
        if (this === target) {
          return fn;
        }

        if (this.constructor !== constructor && Object.getPrototypeOf(this).constructor === constructor) {
          return fn;
        }

        return keep.bind(this, fn, props);
      }
    };
  };
}
//# sourceMappingURL=keepRunning.js.map
