/**
 * @author: vincent
 * @date: 15/5/19
 */
import Button from 'uxcore-button';
import React from 'react';
import classnames from 'classnames';
import assign from 'object-assign';
import Icon from 'uxcore-icon';
import PropTypes from 'prop-types';

import RcDialog from './RcDialog';
import confirm from './confirm';
import i18n from './i18n';


function noop() {
}


const getIEVer = () => {
  if (window) {
    const ua = window.navigator.userAgent;
    const idx = ua.indexOf('MSIE');
    if (idx > 0) {
      // "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64;
      // Trident/6.0; SLCC2; .NET CLR 2.0.50727)"
      return parseInt(ua.substring(idx + 5, ua.indexOf('.', idx)), 10);
    }
    if (ua.match(/Trident\/7\./)) {
      // "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2;
      // .NET CLR 2.0.50727; rv:11.0) like Gecko"
      return 11;
    }
    return 0;
  }
  return 0;
};

class Dialog extends React.Component {
  constructor(props) {
    super(props);

    const { top, left } = props.style || {};
    this.state = {
      contentTop: top,
      contentLeft: left,
      dragged: false,
    };
  }

  componentDidUpdate(prevProps) {
    const { visible } = this.props;
    const { htmlClassName } = prevProps;
    const htmlNode = document.documentElement;
    const supportClassList = !!htmlNode.classList;

    // reset the position of dialog in draggable mode
    if (!prevProps.visible && visible) {
      this.setState({ dragged: false });
    }

    if (htmlClassName) {
      if (visible) {
        if (supportClassList) {
          htmlNode.classList.add(htmlClassName);
        } else {
          htmlNode.className += ` ${htmlClassName}`;
        }
      } else if (supportClassList) {
        htmlNode.classList.remove(htmlClassName);
      } else {
        let cls = htmlNode.className;
        cls = cls.replace(new RegExp(`\\s?${htmlClassName}`), '');
        htmlNode.className = cls;
      }
    }
  }

  saveRef(refName) {
    const me = this;
    return (c) => {
      me[refName] = c;
    };
  }

  handleCancel(e) {
    const { onCancel } = this.props;
    onCancel(e);
  }

  handleOk() {
    const { onOk } = this.props;
    onOk();
  }

  handleDrag(e) {
    const { clientY, clientX } = e;

    this.setState({
      dragged: true,
      contentTop: clientY > 0 ? clientY : 0,
      contentLeft: clientX > 0 ? clientX : 0
    });
  }

  render() {
    const { props } = this;
    const { context = {} } = this;
    const { localePack = {} } = context;
    const locale = { ...i18n[props.locale], ...localePack.Dialog, ...props.localePack }; //merge语言包默认组件props优先级大于ConfigProvider传递语言包大于locale语言环境对应语言包大于默认语言包

    const defaultFooter = [
      <Button
        key="cancel"
        type="secondary"
        size="small"
        onClick={this.handleCancel.bind(this)}
      >
        {locale.cancel}
      </Button>,
      <Button
        key="confirm"
        type="primary"
        size="small"
        onClick={this.handleOk.bind(this)}
      >
        {locale.ok}
      </Button>,
    ];
    const footer = props.footer || defaultFooter;
    const className = classnames({
      [`${props.prefixCls}-noheader`]: !props.title,
      [props.className]: !!props.className,
      [`${props.prefixCls}-confirm`]: props.isConfirm,
    });
    const wrapClassName = classnames({
      [props.wrapClassName]: !!props.wrapClassName,
      'vertical-center-dialog': getIEVer() < 8,
    });

    const { title, style, draggable, ...otherProps } = this.props;
    const { dragged, contentTop, contentLeft } = this.state;

    let newTitle = title;
    let newStyle = { ...style };

    if (draggable) {
      if (dragged) {
        newStyle = {
          ...newStyle,
          position: 'absolute',
          top: contentTop,
          left:contentLeft,
        }
      }
      
      newTitle = (
        <div
          draggable={true}
          onDrag={this.handleDrag.bind(this)}
          onDragEnd={this.handleDrag.bind(this)}
        >
          {title}  
        </div>
      );
    }

    return (
      <RcDialog
        onClose={this.handleCancel.bind(this)}
        footer={footer}
        {...otherProps}
        title={newTitle}
        style={newStyle}
        className={className}
        wrapClassName={wrapClassName}
        visible={props.visible}
        ref={(c) => {
          this.dialog = c;
        }}
      />
    );
  }
}

Dialog.propTypes = {
  onCancel: PropTypes.func,
  onOk: PropTypes.func,
  htmlClassName: PropTypes.string,
  getContainer: PropTypes.func,
  className: PropTypes.string,
  iconClassName: PropTypes.string,
  visible: PropTypes.bool,
  maskClosable: PropTypes.bool,
  title: PropTypes.string,
  closable: PropTypes.bool,
  maskTransitionName: PropTypes.string,
  transitionName: PropTypes.string,
  locale: PropTypes.string,
  wrapClassName: PropTypes.string,
  prefixCls: PropTypes.string,
  draggable: PropTypes.bool,
  localePack: PropTypes.object,
};

Dialog.defaultProps = {
  prefixCls: 'kuma-dlg',
  className: '',
  wrapClassName: '',
  onOk: noop,
  locale: 'zh-cn',
  onCancel: noop,
  width: '520px',
  transitionName: 'dialogSlideDown',
  maskTransitionName: 'dialogFade',
  visible: false,
  closable: true,
  maskClosable: false,
  title: '',
  htmlClassName: '',
  getContainer: undefined,
  iconClassName: undefined,
  draggable: false,
  localePack: undefined
};

function adjustIcon(props, defaultIcon) {
  const icon = props.iconClassName
    ? <Icon name={props.iconClassName} /> : <Icon name={defaultIcon} />;
  return props.icon ? props.icon : icon;
}

Dialog.info = (props) => {
  assign(props, {
    icon: adjustIcon(props, 'tishi-full'),
    okCancel: false,
  });
  return confirm(props, Dialog);
};

Dialog.success = (props) => {
  assign(props, {
    icon: adjustIcon(props, 'chenggong-full'),
    okCancel: false,
  });
  return confirm(props, Dialog);
};

Dialog.error = (props) => {
  assign(props, {
    icon: adjustIcon(props, 'biaodanlei-tongyongqingchu'),
    okCancel: false,
  });
  return confirm(props, Dialog);
};

Dialog.confirm = (props) => {
  assign(props, {
    icon: <Icon name="jinggao-full" />,
  });
  return confirm(props, Dialog);
};

Dialog.contextTypes = {
  localePack: PropTypes.object
}

export default Dialog;
