content: import React from 'react';
  import {BaseMixin, ElementaryMixin, ContentMixin, LsiMixin, Tools} from './../common/common.js';
  
  import Backdrop from './../bricks/backdrop.js';
  import Span from './../bricks/span.js';
  import Link from './../bricks/link.js';
  
  import ItemList from './internal/item-list.js';
  
  import Label from './internal/label.js';
  import InputWrapper from './internal/input-wrapper.js';
  import ItemsInput from './internal/items-input.js';
  import ChoiceMixin from './mixins/choice-mixin.js';
  import InputMixin from './mixins/input-mixin.js';
  
  import SelectOption from './select-option.js';
  
  import './select.less';
  
  export const Select = React.createClass({
  
    //@@viewOn:mixins
    mixins: [
      BaseMixin,
      ElementaryMixin,
      ContentMixin,
      InputMixin,
      ChoiceMixin,
      LsiMixin
    ],
    //@@viewOff:mixins
  
    //@@viewOn:statics
    statics: {
      tagName: 'UU5.Forms.Select',
      classNames: {
        main: 'uu5-forms-select',
        link: 'uu5-forms-select-link',
        open: 'uu5-forms-select-open'
      },
      defaults: {
        childTagName: 'UU5.Forms.Select.option'
      },
      lsi: {
        selectAll: {
          cs: 'Vybrat vše',
          en: 'Select all'
        },
        unselectAll: {
          cs: 'Odebrat vše',
          en: 'Deselect all'
        }
      }
    },
    //@@viewOff:statics
  
    //@@viewOn:propTypes
    propTypes: {
      value: React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.arrayOf(React.PropTypes.string)
      ]),
      multiple: React.PropTypes.bool,
      selectAllEnabled: React.PropTypes.bool,
      allowTags: React.PropTypes.array
    },
    //@@viewOff:propTypes
  
    //@@viewOn:getDefaultProps
    getDefaultProps () {
      return {
        value: null,
        multiple: false,
        allowTags: [],
        selectAllEnabled: false
      };
    },
    //@@viewOff:getDefaultProps
  
    //@@viewOn:standardComponentLifeCycle
    getInitialState () {
      return {
        opened: false
      };
    },
  
    componentWillMount(){
      let value = [];
      if (this.props.value) {
        value = this._valuesToValuesArray(this.props.value);
      }
      if (this.props.onValidate && typeof this.props.onValidate === 'function') {
        this._validateOnChange({value: value, event: null, component: this})
      } else {
        this.setInitial(null, value)
      }
      return this;
    },
  
    componentWillReceiveProps(nextProps) {
      let value = this._valuesToValuesArray(nextProps.value, nextProps.children);
      if (nextProps.controlled) {
        this.setFeedback(nextProps.feedback, nextProps.message, value)
      }
      return this;
    },
    //@@viewOff:standardComponentLifeCycle
  
    //@@viewOn:interface
    isOpened () {
      return this.state.opened;
    },
  
    open (setStateCallback) {
      this.setState({opened: true}, setStateCallback);
      return this;
    },
  
    close (setStateCallback) {
      this.setState({opened: false}, setStateCallback);
      return this;
    },
  
    toggle (setStateCallback) {
      this.setState((state) => ({opened: !state.opened}), setStateCallback);
      return this;
    },
  
    addValue: function (index, setStateCallback) {
      if (this.props.multiple) {
        var indexes = this.getValue() || [];
        var indexPosition = indexes.indexOf(index);
        if (indexPosition === -1) {
          indexes.push(index);
          this.setValue(indexes, setStateCallback);
        } else if (typeof setStateCallback === 'function') {
          setStateCallback();
        }
      } else {
        this.showWarning('notMultiple', 'addValue');
      }
      return this;
    },
  
    removeValue(opt, setStateCallback){
      if (typeof this.props.onChange === 'function') {
        opt.component = this;
        //opt.value = this._itemList.getRenderedChildren()[opt.index].props.value;
        this._itemList.getRenderedChildren().forEach((child)=> {
          let value = child ? child.props.selectedContent || child.props.content || child.props.children || child.props.value : null;
          if (value === opt.value) {
            opt.value = child.props.value;
          }
        });
        this.props.multiple ? this.props.onChange(opt) : this.toggle(() => this.props.onChange(opt));
      } else {
        var values = this.getValue() || [];
        if (opt.index > -1) {
          values.splice(opt.index, 1);
          !values.length && (values = null);
  
          if (!this.isOpened() && this.props.required) {
            if (values !== null) {
              this.setValue(values, setStateCallback);
            } else {
              this.setError(this.props.requiredMessage, null, setStateCallback);
            }
          } else {
            this.setValue(values, setStateCallback);
          }
        } else if (typeof setStateCallback === 'function') {
          setStateCallback();
        }
      }
    },
  
    //@@viewOff:interface
  
    //@@viewOn:overridingMethods
    _valuesToValuesArray(newValue, newChildren){
      let value = [];
      let children = newChildren || this.getChildren();
  
      for (let i = 0; i < children.length; i++) {
        let childValue = children[i].props.value;
        if (typeof newValue === 'string') {
          if (newValue === childValue) {
            value.push(i);
          }
        } else if (newValue && newValue.length > 0) {
          if (newValue.indexOf(childValue) > -1) {
            value.push(i);
          }
        }
      }
  
      return value;
    },
  
    setValue_(value, setStateCallback){
      let result = [];
      let children = this.getChildren();
      for (let i = 0; i < children.length; i++) {
        let childValue = children[i].props.value;
        if (typeof value === 'string') {
          if (value === childValue) {
            result.push(i);
          }
        } else if (value && value.length > 0) {
          if (value.indexOf(childValue) > -1) {
            result.push(i);
          }
        }
      }
  
      this.setState({value: result || []}, setStateCallback);
  
    },
  
    setFeedback_(feedback, message, value, setStateCallback){
      if (typeof value === 'string') {
        value = this._valuesToValuesArray(value);
      }
      this.setState({
        feedback: feedback,
        message: message,
        value: value || []
      }, setStateCallback);
  
      return this;
    },
  
    getValue_(){
      let result = [];
      if (this.state.value) {
        for (let i = 0; i < this.state.value.length; i++) {
          result.push(this._itemList.getRenderedChildren()[this.state.value[i]].props.value)
        }
      }
      return this.props.multiple ? result : result[0];
    },
  
    shouldChildRender_(child) {
      let childTagName = Tools.getChildTagName(child);
      let childTagNames = this.props.allowTags.concat(this.getDefault().childTagName);
      return childTagNames.indexOf(childTagName) > -1;
    },
    //@@viewOff:overridingMethods
  
    //@@viewOn:componentSpecificHelpers
  
    _validateOnChange(opt){
      let result = typeof this.props.onValidate === 'function' ? this.props.onValidate(opt) : null;
      if (result) {
        if (typeof result === 'object') {
          if (result.feedback) {
            this.setFeedback(result.feedback, result.message, result.value);
          } else {
            this.setState({value: opt.value});
          }
        } else {
          this.showError('validateError', null, {context: {event: e, func: this.props.onValidate, result: result}});
        }
      } else if (this.props.required && opt.value.length > 0) {
        this.setSuccess(null, opt.value)
      } else {
        this.setInitial(null, opt.value)
      }
      return this;
    },
  
    _getFeedbackIcon(){
      let icon = this.props.required ? this.props.successGlyphicon : null;
      switch (this.getFeedback()) {
        case 'success':
          icon = this.props.successGlyphicon;
          break;
        case 'warning':
          icon = this.props.warningGlyphicon;
          break;
        case 'error':
          icon = this.props.errorGlyphicon;
          break;
      }
      return icon;
    },
  
    _getBackdropProps () {
      var backdropId = this.getId() + "-backdrop";
  
      return {
        hidden: !this.isOpened(),
        id: backdropId,
        onClick: () => this._onChange({opened: !this.isOpened()})
      };
    },
  
    _getTextInputAttrs () {
      var props = {};
  
      if (!this.state.isReadOnly && !this.isDisabled()) {
        var input = this;
        props.onClick = function () {
          input.open();
        };
      }
  
      return props;
    },
  
    _getItemListProps(){
      let props = {};
      let multiple = this.props.multiple;
  
      props.hidden = !this.isOpened();
      props.ref = (itemList) => this._itemList = itemList;
      props.onChange = (opt) => this._onChange(opt);
  
      props.value = this.state.value;
      props.multiple = this.props.multiple;
  
      return props;
    },
  
    _onChange(opt){
      let multiple = this.props.multiple;
  
      let requiredResult = this._checkRequired((opt && opt.value > -1) ? opt.value : this.state.value);
  
      if (this.isOpened() && opt && opt.value > -1) {
  
        let value = [];
        if (opt.value !== null) {
          if (multiple) {
            if (this.state.value && this.state.value.length > 0) {
              // && (value = Tools.merge([], this.state.value));
              for (let i = 0; i < this.state.value.length; i++) {
                value.push(this.state.value[i]);
              }
            }
            if (opt.value != this.state.value || this.state.value.length === 0) {
              let itemPosition = value.indexOf(opt.value);
              if (itemPosition < 0) {
                value.push(opt.value);
              } else {
                value.splice(itemPosition, 1);
              }
            } else {
              value = [];
            }
          } else {
            value = [opt.value];
          }
        }
  
        let result = value;
  
        if (typeof this.props.onChange === 'function') {
          opt.component = this;
          opt.value = this._itemList.getRenderedChildren()[opt.value].props.value;
          multiple ? this.props.onChange(opt) : this.toggle(() => this.props.onChange(opt));
        } else {
          if (requiredResult) {
            multiple ? this.setInitial(null, result) : this.setInitial(null, result, () => this.toggle());
          } else {
            this.setError(this.props.requiredMessage, null, () => this.toggle());
          }
        }
      } else if (opt && !opt.opened && this.props.required) {
        if (requiredResult) {
          this.toggle(() => this.setSuccess(null, this.state.value));
        } else {
          this.setError(this.props.requiredMessage, null, () => this.toggle());
        }
      } else {
        if (requiredResult) {
          this.toggle(() => this.setInitial(null, this.state.value));
        } else {
          this.setError(this.props.requiredMessage, null, () => this.toggle());
        }
      }
      return this;
    },
  
    _checkRequired(value){
      let result = true;
      if (((!value && value != 0) || value.length < 1) && this.props.required && this.isOpened()) {
        result = false;
      }
  
      return result;
    },
  
    _getMainAttrs(){
      let attrs = this._getInputAttrs();
  
      if (this.isOpened()) {
        attrs.className += ' ' + this.getClassName().open;
      }
  
      return attrs;
    },
  
    _getFeedbackIcon(){
      let icon = this.props.required ? this.props.successGlyphicon : null;
      switch (this.getFeedback()) {
        case 'success':
          icon = this.props.successGlyphicon;
          break;
        case 'warning':
          icon = this.props.warningGlyphicon;
          break;
        case 'error':
          icon = this.props.errorGlyphicon;
          break;
      }
      return icon;
    },
  
    _getItemValues(children){
      let result = [];
      if (this.props.placeholder && children === null) {
        result.push(<Span className={this.getClassName().placeholder} content={this.props.placeholder}/>);
      }
      if (children && this.state.value) {
        for (let i = 0; i < this.state.value.length; i++) {
          let child = children[this.state.value[i]];
          let childContent = child ? child.props.selectedContent || child.props.content || child.props.children || child.props.value : null;
          result.push(childContent);
        }
      }
      return result;
    },
  
    _getHeader(){
      let result;
      if (this.props.selectAllEnabled && this.props.multiple) {
        let label = this._isSelectedAll() ? this.getLSIValue('unselectAll') : this.getLSIValue('selectAll');
        result = <Link content={label} onClick={this._select} className={this.getClassName().link} colorSchema='primary'/>
      }
      return result;
    },
  
    _isSelectedAll() {
      let result = false;
      if (this.props.children && this.state.value && this.props.children.length === this.state.value.length) {
        result = true;
      }
      return result;
    },
  
    _select(){
      let result = [];
      if (this._isSelectedAll()) {
      } else {
        this.props.children && this.props.children.forEach((item, i) => {
          result.push(i);
        });
      }
      this.setState({value: result});
      return this;
    },
  
    _getChildren(){
      let children = [];
      if (this.props.children) {
        let childTagNames = this.props.allowTags.concat(this.getDefault().childTagName);
        React.Children.toArray(this.props.children).forEach((child) => {
          let childTagName = Tools.getChildTagName(child);
          if (childTagNames.indexOf(childTagName) > -1) {
            children.push(child);
          }
        })
      }
      return children;
    },
    //@@viewOff:componentSpecificHelpers
  
    //@@viewOn:render
    render () {
      let inputId = this.getId() + '-input';
      let buttons = !this.isReadOnly() && !this.props.buttonHidden ? [{
        glyphicon: this.isOpened() ? this.props.glyphiconOpened : this.props.glyphiconClosed,
        disabled: this.isDisabled(),
        onClick: () => this._onChange(),
        pressed: this.isOpened(),
        colorSchema: 'default'
      }] : null;
  
      let children = this._getChildren();
  
      return (
        <div {...this._getMainAttrs()}>
          <Label
            for={inputId}
            content={this.props.label}
            colWidth={this._buildColWidthClassName(this.props.labelColWidth)}/>
          {this.getInputWrapper([
              <ItemsInput
                id={inputId}
                name={this.props.name || inputId}
                value={this._getItemValues(children)}
                placeholder={this.props.placeholder}
                multiple={this.props.multiple}
                disabled={this.isDisabled() || this.isLoading()}
                readonly={this.isReadOnly()}
                loading={this.isLoading()}
                onItemClick={(opt) => {
                  this.removeValue(opt)
                }}
                onClick={(!this.isReadOnly() && !this.isDisabled()) ? () => this._onChange() : null}
                glyphicon={this._getFeedbackIcon()}
              />,
  
              <ItemList {...this._getItemListProps()} header={this._getHeader()}>
                {children}
              </ItemList>,
              <Backdrop {...this._getBackdropProps()} />],
            buttons)}
        </div>
      );
    }
    //@@viewOn:render
  });
  
  Select.Option = SelectOption;
  
  export default Select;
  