content: import React from 'react';
  import {Tools} from './../common/common.js';
  import {Span, Glyphicon, Div} from './../bricks/bricks.js';
  
  import './input.less';
  
  export default {
    statics: {
      UU5_Forms_InputMixin: {
        classNames: {
          main: 'uu5-forms-input form-group',
          label: 'uu5-forms-input-label control-label',
          inputWrapper: 'uu5-forms-input-wrapper',
          input: 'uu5-forms-input-input form-control',
          button: 'uu5-forms-input-button',
          message: 'uu5-forms-input-message',
          glyphicon: "uu5-forms-input-glyphicon form-control-feedback",
          size: 'uu5-forms-input-size-',
          hidden: 'uu5-common-hidden',
          infoMessage: 'info'
        }
      }
    },
  
    propTypes: {
      label: React.PropTypes.any,
      message: React.PropTypes.any,
      feedback: React.PropTypes.oneOf(['initial', 'error', 'warning', 'success']),
  
      size: React.PropTypes.oneOf(['lg', 'md', 'sm']),
  
      onChange: React.PropTypes.func,
      onValidate: React.PropTypes.func,
      onChangeFeedback: React.PropTypes.func,
  
      successGlyphicon: React.PropTypes.string,
      warningGlyphicon: React.PropTypes.string,
      errorGlyphicon: React.PropTypes.string,
  
      labelColWidth: React.PropTypes.number,
      inputColWidth: React.PropTypes.number,
  
      labelAttrs: React.PropTypes.object,
      inputWrapperAttrs: React.PropTypes.object,
      inputAttrs: React.PropTypes.object,
      messageAttrs: React.PropTypes.object
    },
  
    // Setting defaults
    getDefaultProps: function () {
      return {
        label: null,
        message: null,
        feedback: 'initial',
        size: 'md',
        onChange: null,
        onValidate: null,
        successGlyphicon: 'uu-glyphicon-ok-circle',
        warningGlyphicon: 'uu-glyphicon-alert-circle',
        errorGlyphicon: 'uu-glyphicon-error-circle',
        labelColWidth: 3,
        inputColWidth: 9,
        labelAttrs: null,
        inputWrapperAttrs: null,
        inputAttrs: null,
        messageAttrs: null
      };
    },
  
    getInitialState: function () {
      return {
        message: this.props.message,
        feedback: this.props.feedback,
        value: this.props.value
      };
    },
  
    componentWillMount: function () {
      var newState = this._validateValue(this.props.value, true);
      if (newState) {
        if (newState.feedback) {
          this._setFeedback(newState.feedback, newState.message, newState.value);
        } else {
          this.setState(newState);
        }
      }
    },
  
    componentDidMount: function () {
      var parentForm = this._getForm();
      parentForm && parentForm.registerFormControl(this.getId(), this);
    },
  
    componentWillReceiveProps: function (nextProps) {
      if (nextProps.id && nextProps.id !== this.props.id) {
        var parentForm = this._getForm();
        if (parentForm) {
          parentForm.unregisterFormControl(this.props.id);
          parentForm.registerFormControl(nextProps.id, this);
        }
      }
  
      var newState = {};
      nextProps.message !== undefined && (newState.message = nextProps.message);
      nextProps.feedback !== undefined && (newState.feedback = nextProps.feedback);
  
      var value;
      nextProps.value !== undefined && (value = nextProps.value);
  
      if (value !== undefined) {
        this.setValue(value, null, newState);
      } else if (Object.keys(newState)) {
        this.setState(newState);
      }
    },
  
    componentWillUnmount: function () {
      var parentForm = this._getForm();
      parentForm && parentForm.unregisterFormControl(this.getId());
    },
  
    // Interface
    isInput: function () {
      return true;
    },
  
    getValue: function () {
      var value;
      if (typeof this.getValue_ === 'function') {
        value = this.getValue_();
      } else {
        value = this.state.value;
      }
      return value;
    },
  
    setValue: function (value, setStateCallback, options) {
      options && options.feedback === '' && (options.feedback = 'initial');
  
      if (typeof this.setTextValue_ === 'function') {
        this.setTextValue_(value, setStateCallback, options);
      } else if (typeof this.setValue_ === 'function') {
        this.setValue_(value, setStateCallback, options);
      } else {
        options = options || {};
        options.value = value;
        this.setState(options, setStateCallback);
      }
      return this;
    },
  
    getFeedback: function () {
      return this.state.feedback;
    },
  
    setFeedback: function (feedback, msg, value, setStateCallback) {
      this.setValue(value === undefined ? this.getValue() : value, setStateCallback, {
        message: msg,
        feedback: feedback
      });
  
      return this;
    },
  
    setError: function (msg, value, setStateCallback) {
      if (typeof this.setError_ === 'function') {
        this.setError_(msg, value, setStateCallback);
      } else {
        this._setFeedback('error', msg, value, setStateCallback);
      }
      return this;
    },
  
    isError: function () {
      return this.getFeedback() === 'error';
    },
  
    setWarning: function (msg, value, setStateCallback) {
      if (typeof this.setWarning_ === 'function') {
        this.setWarning_(msg, value, setStateCallback);
      } else {
        this._setFeedback('warning', msg, value, setStateCallback);
      }
      return this;
    },
  
    isWarning: function () {
      return this.getFeedback() === 'warning';
    },
  
    setSuccess: function (msg, value, setStateCallback) {
      if (typeof this.setSuccess_ === 'function') {
        this.setSuccess_(msg, value, setStateCallback);
      } else {
        this._setFeedback('success', msg, value, setStateCallback);
      }
      return this;
    },
  
    isSuccess: function () {
      return this.getFeedback() === 'success';
    },
  
    setInitial: function (msg, value, setStateCallback) {
      if (typeof this.setInitial_ === 'function') {
        this.setInitial_(msg, value, setStateCallback);
      } else {
        this._setFeedback('initial', msg, value, setStateCallback);
      }
      return this;
    },
  
    isInitial: function () {
      return this.getFeedback() === 'initial';
    },
  
    getMessage: function () {
      return this.state.message;
    },
  
    setStateProps: function (options, setStateCallback) {
      var newState = {};
  
      var value = options.value !== undefined ? options.value : this.state.value;
      options.feedback && (newState.feedback = options.feedback);
      options.message !== undefined && (newState.message = options.message);
      options.disabled !== undefined && (newState.disabled = options.disabled);
      options.hide !== undefined && (newState.hide = options.hide);
  
      Object.keys(newState).length > 0 && this.setValue(value, setStateCallback, newState);
  
      return this;
    },
  
    getResetNewState: function () {
      var newState = this._validateValue(this.props.value, true);
  
      newState = newState || {
          value: this.props.value,
          message: this.props.message,
          feedback: this.props.feedback,
          disabled: this.props.disabled,
          hidden: this.props.hidden
        };
  
      return newState;
    },
  
    reset: function (setStateCallback) {
      if (typeof this.reset_ === 'function') {
        this.reset_(setStateCallback);
      } else {
        this.setState(this.getResetNewState(), setStateCallback);
      }
      return this;
    },
  
    getInputMainAttrs: function () {
      var mainAttrs = this.buildMainAttrs();
  
      mainAttrs.className += ' ' + this.getClassName('main', 'UU5_Forms_InputMixin');
      this.props.size && (mainAttrs.className += ' ' + this.getClassName('size', 'UU5_Forms_InputMixin') + this.props.size);
  
      return mainAttrs;
    },
  
    getInputTagAttrs: function () {
      var inputAttrs = this.props.inputAttrs ? Tools.mergeDeep({}, this.props.inputAttrs) : {};
      inputAttrs.id = this.getId();
      inputAttrs.name = this.getName();
      this.isDisabled() && (inputAttrs.disabled = 'disabled');
  
      inputAttrs.onChange = this._onChange;
  
      inputAttrs.ref = function (input) {
        this.input = input;
      }.bind(this);
  
      return inputAttrs;
    },
  
    getMessageAttrs: function () {
      var msgAttrs = this.props.messageAttrs ? Tools.mergeDeep({}, this.props.messageAttrs) : {};
      var msgClassName = this.getClassName('message', 'UU5_Forms_InputMixin');
      msgClassName += ' bg-' + (this.isInitial() ? this.getClassName('infoMessage', 'UU5_Forms_InputMixin') : this.getFeedback());
      // fixing BootStrap inconsistency
      msgClassName = msgClassName.replace('bg-error', 'bg-danger');
  
      msgAttrs.className = msgAttrs.className ? msgClassName + ' ' + msgAttrs.className : msgClassName;
      return msgAttrs;
    },
  
    getMessageChild: function (msgAttrs) {
      var result = null;
      var message = this.getMessage();
  
      if (message) {
        msgAttrs = msgAttrs || this.getMessageAttrs();
        result = <Div {...msgAttrs} content={message} />;
      }
  
      return result;
    },
  
    getLabelAttrs: function () {
      var labelAttrs = this.props.labelAttrs ? Tools.mergeDeep({}, this.props.labelAttrs) : {};
      var labelClassName = this.getClassName('label', 'UU5_Forms_InputMixin') + ' col-sm-' + this.props.labelColWidth;
      labelAttrs.className = labelAttrs.className ? labelClassName + ' ' + labelAttrs.className : labelClassName;
      labelAttrs.htmlFor = this.getId();
  
      return labelAttrs;
    },
  
    getLabelChild: function (labelAttrs) {
      var result = null;
  
      if (this.props.label !== null) {
        labelAttrs = labelAttrs || this.getLabelAttrs();
        result = React.createElement('label', labelAttrs, React.createElement(Span, { content: this.props.label }));
      }
  
      return result;
    },
  
    getGlyphiconProps: function () {
      var glyphiconProps = null;
  
      var glyphicon;
      switch (this.getFeedback()) {
        case 'error':
          glyphicon = this.props.errorGlyphicon;
          break;
        case 'success':
          glyphicon = this.props.successGlyphicon;
          break;
        case 'warning':
          glyphicon = this.props.warningGlyphicon;
          break;
        default:
          this.props.isRequired && !this.isReadOnly() && !this.isDisabled() && (glyphicon = this.props.successGlyphicon);
          break;
      }
  
      if (glyphicon) {
        glyphiconProps = {
          glyphicon: glyphicon,
          className: this.getClassName('glyphicon', 'UU5_Forms_InputMixin')
        };
      }
  
      return glyphiconProps;
    },
  
    getGlyphiconChild: function (glyphiconProps) {
      glyphiconProps === undefined && (glyphiconProps = this.getGlyphiconProps());
      return glyphiconProps && React.createElement(Glyphicon, glyphiconProps);
    },
  
    getInputWrapperAttrs: function () {
      var inputWrapperAttrs = this.props.inputWrapperAttrs ? Tools.mergeDeep({}, this.props.inputWrapperAttrs) : {};
      var inputColWidth = this.props.label === null ? 12 : this.props.inputColWidth;
      var inputWrapperClassName = this.getClassName('inputWrapper', 'UU5_Forms_InputMixin') + ' col-sm-' + inputColWidth;
      inputWrapperAttrs.className = inputWrapperAttrs.className ? inputWrapperClassName + ' ' + inputWrapperAttrs.className : inputWrapperClassName;
      return inputWrapperAttrs;
    },
  
    // Component Specific Helpers
    _getForm: function () {
      var form = null;
      var parent = this.getParent && this.getParent();
      while (parent) {
        if (typeof parent.isInput === 'function' && parent.isInput()) {
          break;
        } else if (typeof parent.isForm === 'function' && parent.isForm()) {
          form = parent;
          break;
        } else {
          parent = parent.getParent && parent.getParent();
        }
      }
      return form;
    },
  
    _setFeedback: function (feedback, msg, value, setStateCallback) {
      if (typeof this.props.onChangeFeedback === 'function') {
        this.props.onChangeFeedback({
          feedback: feedback,
          message: msg,
          value: value,
          callback: setStateCallback,
          component: this
        });
      } else {
        this.setFeedback(feedback, msg, value, setStateCallback);
      }
      return this;
    },
  
    _validateValue: function (value, init) {
      var result = null;
      var validateResult = null;
  
      if (typeof this.validate_ === 'function') {
        validateResult = this.validate_(value, init);
      }
  
      if (!validateResult && this.props.onValidate) {
        var params = { value: value, component: this };
  
        /*
         * @deprecated input since 03.10. Use component instead of this.
         */
        params.input = this;
  
        validateResult = this.props.onValidate(params);
      }
  
      if (validateResult && typeof validateResult === 'object') {
        result = {};
  
        if (validateResult.feedback && (!init || validateResult.feedback !== 'success')) {
          result.feedback = validateResult.feedback;
        }
        if (validateResult.message !== undefined) {
          result.message = validateResult.message;
        }
        if (validateResult.value !== undefined) {
          result.value = validateResult.value;
        } else {
          result.value = value;
        }
      }
  
      return result;
    }
  };
  