/** @jsx createElement */

'use strict';

import { createElement, Component, PropTypes } from 'rax';
import View from 'nuke-view';
import Touchable from 'nuke-touchable';
import { connectStyle } from 'nuke-theme-provider';
import Icon from 'nuke-icon';
import stylesProvider from '../styles';
/**
 * Radio
 * @description 单选框
 */
class Radio extends Component {
  constructor(props) {
    super(props);
    this.onChange = this.onChange.bind(this);
    const checked = props.checked || false;
    this.state = {
      checked,
      value: props.value || '',
    };
  }

  componentWillMount() {
    if (
      this.context.__group__ &&
      !this.props.ignoreContext &&
      this.context.selectedValue === this.props.value
    ) {
      this.state = {
        checked: true,
      };
    }
  }

  componentWillReceiveProps(nextProps, nextContext) {
    if (nextContext.__group__ && !this.props.ignoreContext) {
      if (
        typeof nextContext === 'object' &&
        nextContext.selectedValue === nextProps.value
      ) {
        this.setState({ checked: true });
      } else {
        this.setState({ checked: false });
      }
    } else if ('checked' in nextProps) {
      if (nextProps.checked !== this.props.checked) {
        this.setState({
          checked: nextProps.checked,
        });
      }
    }
  }

  onChange(e) {
    const { onChange, value, disabled } = this.props;
    if (disabled) return;
    const tmp = this.state.checked;
    if (this.context.__group__ && !this.props.ignoreContext) {
      this.context.onChange(value, e);
    } else if (!('checked' in this.props)) {
      this.setState({
        checked: !tmp,
      });
    }
    onChange(!tmp);
    e.stopPropagation && e.stopPropagation();
  }

  renderInner(props) {
    const {
      style,
      disabled,
      themeStyle,
      checkedStyle,
      type,
      disabledStyle,
      size,
    } = props;
    if (!this.state.checked) return null;


    if (type === 'dot') {
      let dotStyle = Object.assign({}, themeStyle['dot-inner'], themeStyle[`dot-inner-${size}`],
        checkedStyle && checkedStyle.color ? { backgroundColor: checkedStyle.color } : {},
      );
      if (disabled) {
        dotStyle = Object.assign({}, dotStyle, themeStyle['dot-inner-disabled'], {
          backgroundColor:
            (disabledStyle && disabledStyle.color) ||
            themeStyle['dot-inner-disabled'].backgroundColor,
        });
      }
      return <View style={dotStyle} />;
    }
    const innerStyle = Object.assign({},
      themeStyle[`icon-${size}`],
      themeStyle[`${type}-inner`],
      { color: (style && style.color) || themeStyle[`${type}-inner-checked`].color },
      disabled ? {
        color:
          (disabledStyle && disabledStyle.color) ||
          themeStyle[`${type}-inner-disabled`].color,
      } : {}
    );

    return <Icon style={innerStyle} name="right" onClick={this.onChange} />;
  }

  render() {
    const {
      size,
      style,
      disabled,
      type,
      themeStyle,
      checkedStyle,
      disabledStyle,
      touchStyle,
    } = this.props;

    const { checked } = this.state;
    const elementTouchStyle = Object.assign(
      {},
      themeStyle[`touch-${size}`],
      touchStyle
    );

    const wrapStyle = Object.assign(
      {},
      themeStyle[`wrap-${size}`],
      themeStyle[`wrap-${type}`],

      checked
        ? Object.assign({}, themeStyle[`wrap-${type}-checked`], checkedStyle)
        : {},
      disabled
        ? Object.assign({}, themeStyle[`wrap-${type}-disabled`], disabledStyle)
        : {},
      checked && disabled
        ? Object.assign({}, themeStyle[`wrap-${type}-checked-disabled`])
        : {},
      style,
    );


    return (
      <Touchable style={elementTouchStyle} onPress={this.onChange}>
        <View style={wrapStyle}>{this.renderInner(this.props)}</View>
      </Touchable>
    );
  }
}
Radio.displayName = 'Radio';
Radio.propTypes = {
  /**
   * 受控选择  controlled select
   */
  checked: PropTypes.boolean,
  /**
   * 单选尺寸  size of radio
   * @enumdesc small,medium
   */
  size: PropTypes.oneOf(['small', 'medium']),
  /**
   * 受控禁用  controlled disabled
   */
  disabled: PropTypes.boolean,
  /**
   * 状态变更回调  status change callback
   */
  onChange: PropTypes.func,
  /**
   * 外观类型  appearance type
   * @enumdesc normal,list,empty,dot
   */
  type: PropTypes.oneOf(['normal', 'list', 'empty', 'dot']),
  /**
   * 单选group的选中值，配合DataSource使用
   * value of radio group.
   */
  value: PropTypes.string,
  /**
   * 选中样式，选中状态下会覆盖style
   */
  checkedStyle: PropTypes.object,
  /**
   * 禁用样式，禁用状态下会覆盖style
   */
  disabledStyle: PropTypes.object,
  /**
   * 点击区域样式，通常点击区域要大于外观区域
   */
  touchStyle: PropTypes.object,
  /**
   * 忽略上层父级 context，当 radio.group 的子级存在非 group 模式的 radio 时需设置为 false
   * ignore context passing. usually use the nested with radio group
   */
  ignoreContext: PropTypes.boolean,
};

Radio.defaultProps = {
  size: 'medium',
  disabled: false,
  onChange: () => { },
  type: 'normal',
  value: '',
  checkedStyle: {},
  disabledStyle: {},
  touchStyle: {},
  ignoreContext: false,
};
Radio.contextTypes = {
  onChange: PropTypes.func,
  __group__: PropTypes.bool,
  selectedValue: PropTypes.any,
};

export default connectStyle(stylesProvider)(Radio);
