/** @jsx createElement */
import { Component, createElement, PropTypes } from 'rax';
import View from 'nuke-view';
import { isWeb, appInfo } from 'nuke-env';
import Text from 'nuke-text';
import Mask from 'nuke-mask';
import Button from 'nuke-button';
import ThemeProvider from 'nuke-theme-provider';
import stylesProvider from '../styles';
import CustomDialogLocales from './locale';

const { connectStyle } = ThemeProvider;

class Dialog extends Component {
  constructor(props) {
    super(props);
    this.show = this.show.bind(this);
    this.hide = this.hide.bind(this);
    this.onShow = this.onShow.bind(this);
    this.onHide = this.onHide.bind(this);
    this.wrapPress = this.wrapPress.bind(this);
    this.maskTouchMove = this.maskTouchMove.bind(this);
    this.contentTouchMove = this.contentTouchMove.bind(this);
    this.isIOS = appInfo.platform.toLowerCase() === 'ios';
    if (props.type) {
      this.isIOS = props.type.toLowerCase() === 'iOS';
    }
  }

  onShow() {
    this.props.onShow && this.props.onShow();
  }
  onHide() {
    this.props.onHide && this.props.onHide();
  }
  hide() {
    this.refs.modalMask && this.refs.modalMask.hide();
  }
  show() {
    this.refs.modalMask && this.refs.modalMask.show();
  }

  wrapPress(e) {
    if (isWeb) {
      e.stopPropagation();
    }
  }
  fixBody() {
    if (isWeb) {
      const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
      document.body.style.cssText += `position:fixed;top:-${scrollTop}px;`;
    }
  }
  contentTouchMove(e) {
    if (isWeb) {
      this.fixBody();
      e.stopPropagation();
    }
  }
  maskTouchMove(e) {
    if (isWeb) {
      this.fixBody();
    }
  }
  getHeader() {
    const { title, themeStyle: styles } = this.props;
    if (title) {
      if (typeof title === 'string') {
        return (
          <Text
            fixedFont
            style={[styles.title, this.isIOS ? null : styles['md-title']]}
          >
            {title}
          </Text>
        );
      }
      return title;
    }
    return null;
  }
  cancel(e, btnPressCb) {
    const { onCancel } = this.props;
    if (btnPressCb) {
      btnPressCb.call(this, e);
    } else {
      this.refs.modalMask.hide();

      onCancel && onCancel();
    }
  }
  confirm(e, btnPressCb) {
    const { onConfirm } = this.props;
    if (btnPressCb) {
      btnPressCb.call(this, e);
    } else {
      this.refs.modalMask.hide();

      onConfirm && onConfirm();
    }
  }
  getFooter() {
    const {
      showCancelButton,
      showConfirmButton,
      confirmButtonStyle,
      cancelButtonStyle,
      footerStyle,
      themeStyle: styles,
    } = this.props;
    let footerDom = [];
    const locale = this.getLocale();
    const btnStyles = this.isIOS ? styles.btn : styles['md-btn'];
    const footerStyles = Object.assign(
      {},
      styles.footer,
      this.isIOS ? null : styles['md-footer'],
      footerStyle
    );
    let cancelDom;
    let confirmDom;
    if (!showConfirmButton && !showCancelButton) return null;
    if (showCancelButton) {
      cancelDom = (
        <Button
          rect
          fixedFont
          style={Object.assign(
            {},
            btnStyles,
            this.isIOS ? null : styles['md-btn-weak'],
            showConfirmButton ? styles['btn-left'] : null,
            this.isIOS && showConfirmButton ? null : styles['md-btn-left'],
            cancelButtonStyle
          )}
          type="normal"
          onPress={(e) => {
            this.cancel(e, null);
          }}
        >
          {locale.cancel}
        </Button>
      );
    }
    if (showConfirmButton) {
      confirmDom = (
        <Button
          rect
          style={[
            btnStyles,
            showCancelButton ? styles['btn-right'] : null,
            confirmButtonStyle,
          ]}
          type="normal"
          onPress={(e) => {
            this.confirm(e, null);
          }}
        >
          {locale.confirm}
        </Button>
      );
    }

    footerDom = (
      <View role="footer" style={footerStyles}>
        {cancelDom}
        {confirmDom}
      </View>
    );
    return footerDom;
  }
  getLocale() {
    const { locale = {} } = this.props;
    const localeName = 'en';
    return Object.assign(
      {},
      CustomDialogLocales[localeName] || CustomDialogLocales.en,
      locale
    );
  }
  getContent() {
    const { content, themeStyle: styles, children } = this.props;
    if (children) {
      return children;
    }
    if (content) {
      if (typeof content === 'string') {
        return (
          <Text
            fixedFont
            style={[styles.content, this.isIOS ? null : styles['md-content']]}
          >
            {content}
          </Text>
        );
      }
      return content;
    }
    return null;
  }
  render() {
    const {
      contentStyle = {},
      maskClosable,
      renderMask,
      style,
    } = this.props;
    const styles = this.props.themeStyle;
    const dialogContent = (
      <View
        data-role="dialogmain"
        style={[
          styles.main,
          this.isIOS ? null : styles['md-main'],
          contentStyle,
        ]}
        onClick={this.wrapPress}
        onTouchmove={this.contentTouchMove}
      >
        {this.getHeader()}
        {this.getContent()}
        {this.getFooter()}
      </View>
    );
    return renderMask ? (
      <Mask
        defaultVisible={false}
        onShow={this.onShow}
        onHide={this.onHide}
        ref="modalMask"
        animate={false}
        noPress
        style={[styles.mask, isWeb ? styles.maskWeb : {}, style]}
        maskClosable={maskClosable}
        onTouchmove={this.maskTouchMove}
      >
        {dialogContent}
      </Mask>
    ) : (
      dialogContent
    );
  }
}

Dialog.defaultProps = {
  onHide: () => { },
  onShow: () => { },
  maskClosable: true,
  contentStyle: {},
  children: null,
  showCancelButton: false,
  showConfirmButton: false,
  renderMask: true,
};
Dialog.propTypes = {
  onHide: PropTypes.func,
  onShow: PropTypes.func,
  renderMask: PropTypes.boolean,
  children: PropTypes.any,
  contentStyle: PropTypes.any,
};
Dialog.displayName = 'Dialog';
const StyledDialog = connectStyle(stylesProvider)(Dialog);

export default StyledDialog;
