'use strict';

/** @jsx createElement */
import { Component, createElement, PropTypes } from 'rax';
import View from 'nuke-view';
import { isWeb } from 'nuke-env';
import Touchable from 'nuke-touchable';
import { connectStyle } from 'nuke-theme-provider';
import Icon from 'nuke-icon';
import Input from 'nuke-normal-input';
import stylesProvider from './styles';

const noop = () => {};

class NumberPicker extends Component {
  constructor(props) {
    super(props);

    let value;
    if ('value' in props) {
      value = props.value;
    } else {
      value = props.defaultValue;
    }
    value = this.getValidValue(value);
    this.state = {
      value,
      error: false,
      focused: false,
      displayValue: value,
    };
    ['onAdd', 'onReduce', 'onChange', 'onFocus', 'onBlur'].forEach((m) => {
      this[m] = this[m].bind(this);
    });
  }
  componentWillReceiveProps(nextProps) {
    // todo: dynamic min & max
    if ('value' in nextProps) {
      const value = this.getValidValue(nextProps.value);
      this.setState({
        value,
        displayValue: value,
      });
    }
  }
  onAdd() {
    const { max, step } = this.props;
    const nextValue = parseInt(this.state.value, 10) + parseInt(step, 10);

    if (!max || nextValue <= max) {
      this.setValue(nextValue);
    }
  }
  onReduce() {
    const { min, step } = this.props;
    const nextValue = parseInt(this.state.value, 10) - parseInt(step, 10);

    if (!min || nextValue >= min) {
      this.setValue(nextValue);
    }
  }
  onChange(val, e) {
    if (this.props.editable) {
      this.setState({
        displayValue: val,
      });
    }
    // alert(val);
    this.setValue(val);
  }
  onFocus() {
    this.setState({ focused: true });
  }

  onBlur(e) {
    // debugger;
    const val = this.refs.numberpicker.wrappedInstance.getValue();
    // alert(val);

    this.setValue(val);

    this.setState({ focused: false });
  }
  setValue(displayValue) {
    let flag;
    let value;
    let error = false;
    const { disabled, autoCorrect, onChange } = this.props;

    if (disabled) {
      return;
    }

    value = this.state.value;
    const validValue = this.getValidValue(displayValue);

    if (autoCorrect) {
      value = displayValue = validValue;
    } else {
      error = validValue.toString() !== displayValue.toString();
      if (!error) {
        value = validValue;
      }
    }

    if (value !== this.state.value || ((flag = true) && value.toString() !== this.state.displayValue.toString())) {
      if (!('value' in this.props)) {
        this.setState({
          value,
          displayValue,
        });
      } else if (!error) {
        this.setState({
          displayValue: this.state.value,
        });
      }

      this.setState({
        error,
      });

      if (!flag) {
        onChange(value);
      }
    } else {
      this.setState({
        error,
      });
    }
  }

  getValue() {
    return this.state.value;
  }
  getValidValue(value) {
    const { min, max } = this.props;

    value = value === '' ? this.state.value : parseInt(value, 10);
    value = isNaN(value) ? this.state.value : value < min ? min : value > max ? max : value;

    return value;
  }
  render() {
    const { value, displayValue, focused, error } = this.state;
    const styles = this.props.themeStyle;
    const inputWrapStyle = Object.assign({}, styles['input-wrap'], error ? styles['error-input-wrap'] : {});
    const { min, max, step, disabled, editable, autoFocus, style = {} } = this.props;
    const inputAttrs = {};
    if (disabled || !editable) {
      inputAttrs.disabled = true;
    }
    const inputStyle = Object.assign(
      {},
      styles.input,
      isWeb ? styles['input-ff'] : {},
      disabled || inputAttrs.disabled ? styles['input-disabled'] : null,
      error ? styles['error-input'] : {}
    );

    const reduceDisabled = disabled || value <= min || value - step < min;
    const addDisabled = disabled || value >= max || value + step > max;
    return (
      <View style={[styles['number-picker'], style]}>
        <Touchable style={[styles.reduce, reduceDisabled ? styles['disabled-button'] : {}]} onPress={this.onReduce}>
          <Icon style={[styles.icon, reduceDisabled ? styles['icon-disabled'] : {}]} name="minus" />
        </Touchable>

        <Input
          inputStyle={inputStyle}
          type="number"
          fixedFont
          ref="numberpicker"
          style={inputWrapStyle}
          materialDesign={false}
          min={min}
          max={max}
          step={step}
          autoFocus={autoFocus}
          {...inputAttrs}
          value={focused || error ? displayValue : value}
          onFocus={this.onFocus}
          onBlur={this.onBlur}
          onChange={this.onChange}
        />
        <Touchable style={[styles.add, addDisabled ? styles['disabled-button'] : {}]} onPress={this.onAdd}>
          <Icon style={[styles.icon, addDisabled ? styles['icon-disabled'] : {}]} name="add" />
        </Touchable>
      </View>
    );
  }
}

NumberPicker.defaultProps = {
  step: 1,
  defaultValue: 0,
  editable: true,
  disabled: false,
  autoFocus: false,
  autoCorrect: false,
  onChange: noop,
  style: {},
  themeStyle: {},
};

NumberPicker.propTypes = {
  min: PropTypes.number,
  max: PropTypes.number,
  step: PropTypes.number,
  value: PropTypes.number,
  editable: PropTypes.bool,
  disabled: PropTypes.bool,
  autoFocus: PropTypes.bool,
  autoCorrect: PropTypes.bool,
  defaultValue: PropTypes.number,
  onChange: PropTypes.func,
  style: PropTypes.any,
  themeStyle: PropTypes.any,
};
NumberPicker.displayName = 'NumberPicker';

const StyledNumberPicker = connectStyle(stylesProvider, { withRef: true })(NumberPicker);

export default StyledNumberPicker;
