'use strict';

exports.__esModule = true;

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _react = require('react');

var _lodash = require('lodash.isundefined');

var _lodash2 = _interopRequireDefault(_lodash);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var htmlValidationAttrs = ['min', 'max', 'minLength', 'maxLength', 'pattern', 'required', 'step'];
var htmlValidationTypes = ['email', 'date', 'datetime', 'number', 'tel', 'url'];

var getFieldValue = function getFieldValue(event) {
  return event && event.target && !(0, _lodash2.default)(event.target.value) ? event.target.value : event;
};

var AvBaseInput = function (_Component) {
  _inherits(AvBaseInput, _Component);

  function AvBaseInput(props) {
    _classCallCheck(this, AvBaseInput);

    var _this = _possibleConstructorReturn(this, _Component.call(this, props));

    _this.state = { value: '' };
    _this.validations = {};
    _this.value = '';
    _this.onKeyUpHandler = _this.onKeyUpHandler.bind(_this);
    _this.onInputHandler = _this.onInputHandler.bind(_this);
    _this.onBlurHandler = _this.onBlurHandler.bind(_this);
    _this.onFocusHandler = _this.onFocusHandler.bind(_this);
    _this.onChangeHandler = _this.onChangeHandler.bind(_this);
    _this.validate = _this.validate.bind(_this);
    return _this;
  }

  AvBaseInput.prototype.componentWillMount = function componentWillMount() {
    this.value = this.getDefaultValue().value;
    this.setState({ value: this.value });
    this.updateValidations();
  };

  AvBaseInput.prototype.componentWillUpdate = function componentWillUpdate(nextProps) {
    if (nextProps.value !== this.props.value) {
      this.value = nextProps.value;
      this.setState({ value: nextProps.value });
    }
    if (nextProps !== this.props) {
      this.updateValidations(nextProps);
    }
  };

  AvBaseInput.prototype.componentWillUnmount = function componentWillUnmount() {
    this.context.FormCtrl.unregister(this);
  };

  AvBaseInput.prototype.onKeyUpHandler = function onKeyUpHandler(event) {
    if (event && event.target && event.target.validity && event.target.validity.badInput !== this.context.FormCtrl.isBad[this.props.name] && (event.target.validity.badInput !== false || this.context.FormCtrl.isBad[this.props.name] !== undefined)) {
      this.context.FormCtrl.setBad(this.props.name, event.target.validity.badInput);
      this.validate();
    }
    this.props.onKeyUp && this.props.onKeyUp(event);
  };

  AvBaseInput.prototype.onInputHandler = function onInputHandler(_value) {
    this.value = getFieldValue(_value);
    this.validateEvent('onInput');
    !this.context.FormCtrl.isTouched[this.props.name] && this.context.FormCtrl.setTouched(this.props.name);
  };

  AvBaseInput.prototype.onBlurHandler = function onBlurHandler(_value) {
    this.value = getFieldValue(_value);
    this.validateEvent('onBlur');
    !this.context.FormCtrl.isTouched[this.props.name] && this.context.FormCtrl.setTouched(this.props.name);
  };

  AvBaseInput.prototype.onFocusHandler = function onFocusHandler(_value) {
    this.value = getFieldValue(_value);
    this.validateEvent('onFocus');
  };

  AvBaseInput.prototype.onChangeHandler = function onChangeHandler(_value) {
    this.value = getFieldValue(_value);
    this.validateEvent('onChange');
    !this.context.FormCtrl.isDirty[this.props.name] && this.context.FormCtrl.setDirty(this.props.name);
  };

  AvBaseInput.prototype.getDefaultValue = function getDefaultValue() {
    var key = 'defaultValue';

    if (this.props.type === 'checkbox') {
      key = 'defaultChecked';
    }

    var value = this.props[key] || this.context.FormCtrl.getDefaultValue(this.props.name) || '';

    return { key: key, value: value };
  };

  AvBaseInput.prototype.getValidationEvent = function getValidationEvent() {
    return this.props.validationEvent ? this.props.validationEvent : this.context.FormCtrl.validationEvent;
  };

  AvBaseInput.prototype.getValidatorProps = function getValidatorProps() {
    var _this2 = this;

    var state = this.props.state && this.context.FormCtrl.getInputState(this.props.name);
    var htmlValAttrs = Object.keys(this.props.validate).filter(function (val) {
      return htmlValidationAttrs.indexOf(val) > -1;
    }).reduce(function (result, item) {
      result[item] = _this2.props.validate[item].value || _this2.props.validate[item];
      return result;
    }, {});

    var newProps = _extends({
      onKeyUp: this.onKeyUpHandler,
      onBlur: this.onBlurHandler,
      onInput: this.onInputHandler,
      onFocus: this.onFocusHandler,
      onChange: this.onChangeHandler,
      value: this.value
    }, htmlValAttrs);

    if (state) {
      newProps.state = state;
    }

    return newProps;
  };

  AvBaseInput.prototype.getValue = function getValue() {
    return this.value;
  };

  AvBaseInput.prototype.reset = function reset() {
    this.value = this.getDefaultValue().value;
    this.context.FormCtrl.setDirty(this.props.name, false);
    this.context.FormCtrl.setTouched(this.props.name, false);
    this.context.FormCtrl.setBad(this.props.name, false);
    this.setState({ value: this.value });
    this.validate();
    this.props.onReset && this.props.onReset(this.value);
  };

  AvBaseInput.prototype.validateEvent = function validateEvent(eventName) {
    if (this.getValidationEvent() === eventName) {
      this.setState({ value: this.value });
      this.validate();
    }
    this.props[eventName] && this.props[eventName](this.value);
  };

  AvBaseInput.prototype.validate = function validate() {
    this.context.FormCtrl.validate(this.props.name);
  };

  AvBaseInput.prototype.updateValidations = function updateValidations() {
    var _this3 = this;

    var props = arguments.length <= 0 || arguments[0] === undefined ? this.props : arguments[0];

    this.validations = Object.assign({}, props.validate);

    if (htmlValidationTypes.indexOf(props.type) > -1) {
      this.validations[props.type] = this.validations[props.type] || true;
    }

    Object.keys(props).filter(function (val) {
      return htmlValidationAttrs.indexOf(val) > -1;
    }).forEach(function (attr) {
      if (props[attr]) {
        _this3.validations[attr] = _this3.validations[attr] || { value: props[attr] };
      } else {
        delete _this3.validations[attr];
      }
    });

    this.context.FormCtrl.register(this);
    this.validate();
  };

  return AvBaseInput;
}(_react.Component);

AvBaseInput.propTypes = {
  name: _react.PropTypes.string.isRequired,
  validationEvent: _react.PropTypes.oneOf(['', 'onInput', 'onChange', 'onBlur', 'onFocus']),
  validate: _react.PropTypes.object,
  value: _react.PropTypes.any,
  state: _react.PropTypes.bool,
  type: _react.PropTypes.string,
  onKeyUp: _react.PropTypes.func,
  onInput: _react.PropTypes.func,
  onFocus: _react.PropTypes.func,
  onBlur: _react.PropTypes.func,
  onChange: _react.PropTypes.func,
  onReset: _react.PropTypes.func
};
AvBaseInput.contextTypes = {
  FormCtrl: _react.PropTypes.object.isRequired
};
AvBaseInput.defaultProps = {
  validationEvent: '',
  validate: {}
};
exports.default = AvBaseInput;