import React, { Component } from 'react';
import './index.less';
import { Modal, Button, Tooltip } from 'antd';
import Assets from '@src/components/Assets';
import { asyncSMessage } from '@src/services/AsyncTools';
import { Icon as GIcon } from '../Icon';
import { Button as GButton } from '../Button';
import RadioItem from '../RadioItem';
import { User } from '../../stores/user';
import { Common } from '../../stores/common';
import { Main } from '../../stores/main';
import { MobileArea, WechatPcAppId, PcUrl } from '../../../Constant';
import { DefaultInput, SelectInput, VerificationInput } from '../Input';

const LOGIN_PHONE = 'LOGIN_PHONE';
const LOGIN_WX = 'LOGIN_WX';
const BIND_PHONE = 'BIND_PHONE';
const BIND_WX = 'BIND_WX';
const BIND_WX_ERROR = 'BIND_WX_ERROR';

export default class Login extends Component {
  constructor(props) {
    super(props);
    this.validNumber = 0;
    this.needScan = true;
    this.state = { scanNumber: 0, type: LOGIN_WX, empty: {}, data: { area: MobileArea[0].value } };
    this.validMobileNumber = 0;
    this.validEmailNumber = 0;
    window.addEventListener(
      'message',
      event => {
        if (typeof event.data === 'string' && event.data.indexOf('code:') === 0) {
          if (!this.needScan) {
            return;
          }
          this.needScan = false;
          const code = event.data.split(':')[1];
          if (this.state.type === LOGIN_WX) {
            this.scanLogin(code);
          } else if (this.state.type === BIND_WX) {
            this.scanBind(code);
          }
        }
      },
      false,
    );
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.user.needLogin && !this.init) {
      this.init = true;
      Main.getContract('register').then(result => {
        this.setState({ registerContract: result });
      });
      Main.getContract('privacy').then(result => {
        this.setState({ privacyContract: result });
      });
    }
  }

  close() {
    User.closeLogin();
  }

  login() {
    const { data, needEmail, mobileError, validError, emailError, empty } = this.state;
    const { area, mobile, mobileVerifyCode, email } = data;
    if (mobileError || emailError || validError) return;
    if (!area || !mobile || !mobileVerifyCode || (needEmail && !email)) {
      empty[LOGIN_PHONE] = { mobile: !mobile, mobileVerifyCode: !mobileVerifyCode, email: !email };
      this.setState({ empty });
      return;
    }
    empty[LOGIN_PHONE] = {};
    this.setState({ empty });
    User.login(area, mobile, mobileVerifyCode, email, null, false)
      .then(result => {
        if (result.bindWechat) {
          this.close();
        } else {
          this.changeType(BIND_WX);
        }
      })
      .catch(err => {
        if (err.message.indexOf('验证码') >= 0) {
          this.setState({ validError: err.message });
        } else if (err.message.indexOf('邮箱') >= 0) {
          this.setState({ emailError: err.message });
        } else {
          this.setState({ mobileError: err.message });
        }
      });
  }

  bind() {
    const { data, needEmail, mobileError, emailError, validError, empty } = this.state;
    const { area, mobile, mobileVerifyCode, email } = data;
    if (mobileError || emailError || validError) return;
    if (!area || !mobile || !mobileVerifyCode || (needEmail && !email)) {
      empty[BIND_PHONE] = { mobile: !mobile, mobileVerifyCode: !mobileVerifyCode, email: !email };
      this.setState({ empty });
      return;
    }
    empty[BIND_PHONE] = {};
    this.setState({ empty });
    User.bind(area, mobile, mobileVerifyCode, email)
      .then(() => {
        this.close();
      })
      .catch(err => {
        if (err.message.indexOf('验证码') >= 0) {
          this.setState({ validError: err.message });
        } else if (err.message.indexOf('邮箱') >= 0) {
          this.setState({ emailError: err.message });
        } else {
          this.setState({ mobileError: err.message });
        }
      });
  }

  scanLogin(code) {
    User.loginWechat(code, true, false)
      .then(result => {
        this.needScan = false;
        if (result.bindMobile) {
          this.close();
        } else {
          this.changeType(BIND_PHONE);
        }
      })
      .catch(err => {
        this.needScan = true;
        if (err.message !== '登录失败') {
          asyncSMessage(err.message, 'error');
        }
      });
  }

  scanBind(code) {
    User.loginWechat(code, false, false)
      .then(() => {
        this.needScan = false;
        this.close();
      })
      .catch(() => {
        this.needScan = true;
        this.changeType(BIND_WX_ERROR);
      });
  }

  changeData(field, value) {
    let { data, empty } = this.state;
    data = data || {};
    empty = empty || {};
    empty[this.state.type] = empty[this.state.type] || {};
    data[field] = value;
    if (value) empty[this.state.type][field] = !value;
    this.setState({ data, empty });
  }

  validMobile(login) {
    const { data } = this.state;
    const { area, mobile } = data;
    if (!area || !mobile) return;
    this.validMobileNumber += 1;
    const number = this.validMobileNumber;
    User.validWechat(area, mobile)
      .then(result => {
        if (result) {
          this.setState({ mobileError: '' });
          return User.validMobile(area, mobile).then(r => {
            if (number !== this.validMobileNumber) return;
            this.setState({ needEmail: r });
          });
        }
        this.setState({ needEmail: false });
        return login ? Promise.resolve() : Promise.reject(new Error('该手机已绑定其他账号,请更换手机号码'));
      })
      .catch(err => {
        this.setState({ mobileError: err.message });
      });
  }

  validEmail() {
    const { data } = this.state;
    const { email } = data;
    if (!email) return;
    this.validEmailNumber += 1;
    const number = this.validEmailNumber;
    User.validEmail(email)
      .then(result => {
        if (number !== this.validEmailNumber) return Promise.resolve();
        if (result) {
          this.setState({ emailError: '' });
          return Promise.resolve();
        }
        return Promise.reject(new Error('该邮箱已绑定其他账号,请更换邮箱地址'));
      })
      .catch(err => {
        this.setState({ emailError: err.message });
      });
  }

  sendValid() {
    const { data, mobileError } = this.state;
    const { area, mobile } = data;
    if (!area || !mobile || mobileError) return Promise.reject();
    return Common.sendSms(area, mobile)
      .then(result => {
        if (result) {
          asyncSMessage('发送成功');
          this.setState({ mobileError: '', validError: '' });
        } else {
          throw new Error('发送失败');
        }
      })
      .catch(err => {
        this.setState({ mobileError: err.message });
        throw err;
      });
  }

  changeType(nextType) {
    let { scanNumber } = this.state;
    if (nextType === LOGIN_WX || nextType === BIND_WX) {
      scanNumber += 1;
    }
    this.setState({ scanNumber, type: nextType, empty: {}, mobileError: '', emailError: '', validError: '', data: { area: MobileArea[0].value } });
  }

  render() {
    const { type } = this.state;
    const { user } = this.props;
    return (
      <Modal
        ref={ref => {
          this.modalR = ref;
        }}
        wrapClassName={`login-modal ${type}`}
        visible={user.needLogin}
        footer={null}
        closable={false}
        width={470}
      >
        {this.renderBody(type)}
        <GIcon
          name="close"
          onClick={() => {
            if (type === BIND_WX_ERROR) {
              // 绑定微信错误,返回重新绑定微信
              this.changeType(BIND_WX);
            } else {
              User.closeLogin(new Error('no login'));
              this.changeType(LOGIN_WX);
            }
          }}
        />
      </Modal>
    );
  }

  renderBody(type) {
    switch (type) {
      case LOGIN_WX:
        return this.renderLoginWx();
      case BIND_PHONE:
        return this.renderBindPhone();
      case BIND_WX:
        return this.renderBindWx();
      case BIND_WX_ERROR:
        return this.renderBindWxError();
      case LOGIN_PHONE:
      default:
        return this.renderLoginPhone();
    }
  }

  renderLoginPhone() {
    const { needEmail, registerContract = {}, privacyContract, empty = {} } = this.state;
    const emptyError = empty[LOGIN_PHONE] || {};
    return (
      <div className="body">
        <div className="title">手机号登录</div>
        <div className="tip" hidden={!needEmail}>
          <Assets name="notice" />
          该手机号尚未注册,将自动为您注册账户
        </div>
        <SelectInput
          placeholder="请输入手机号"
          selectValue={this.state.data.area}
          select={MobileArea}
          value={this.state.data.mobile}
          error={this.state.mobileError}
          empty={emptyError.mobile}
          onSelect={value => {
            this.changeData('area', value);
            this.validMobile(true);
          }}
          onChange={e => {
            this.changeData('mobile', e.target.value);
            this.validMobile(true);
          }}
        />
        <VerificationInput
          placeholder="请输入验证码"
          value={this.state.data.mobileVerifyCode}
          error={this.state.validError}
          empty={emptyError.mobileVerifyCode}
          onSend={() => {
            return this.sendValid();
          }}
          onChange={e => {
            this.changeData('mobileVerifyCode', e.target.value);
            this.setState({ validError: '' });
          }}
        />
        {needEmail && (
          <DefaultInput
            placeholder="请输入邮箱"
            value={this.state.data.email}
            empty={emptyError.email}
            error={this.state.emailError}
            onChange={e => {
              this.changeData('email', e.target.value);
              this.validEmail();
            }}
          />
        )}
        {needEmail && (
          <div className="m-b-2">
            <RadioItem checked theme="white" className="m-r-5" />
            我已同意{' '}
            <a href={`/contract/${registerContract.key}`} target="_blank">
              《{registerContract.title}》
            </a>{' '}
            <a href={`/contract/${privacyContract.key}`} target="_blank">
              《{privacyContract.title}》
            </a>
            。
          </div>
        )}
        <Button
          type="primary"
          size="large"
          block
          onClick={() => {
            this.login();
          }}
        >
          登录
        </Button>
        <Tooltip overlayClassName="gray" placement="left" title="微信扫码登录">
          <a
            className="other"
            onClick={() => {
              this.changeType(LOGIN_WX);
            }}
          >
            <Assets name="code" />
          </a>
        </Tooltip>
      </div>
    );
  }

  renderLoginWx() {
    return (
      <div className="body">
        <div className="title">微信扫码登录</div>
        <div className="qr-code">
          <iframe
            key={this.state.scanNumber}
            frameBorder="0"
            src={`/login.html?appid=${WechatPcAppId}&redirectUri=${encodeURIComponent(PcUrl)}`}
            width="300"
            height="300"
          />
          <div className="text">请使用微信扫描二维码登录</div>
        </div>
        <Tooltip overlayClassName="gray" placement="left" title="手机号登录">
          <a
            className="other"
            onClick={() => {
              this.changeType(LOGIN_PHONE);
            }}
          >
            <Assets name="phone" />
          </a>
        </Tooltip>
      </div>
    );
  }

  renderBindPhone() {
    const { needEmail, registerContract = {}, privacyContract = {}, empty = {} } = this.state;
    const emptyError = empty[BIND_PHONE] || {};
    return (
      <div className="body">
        <div className="title">绑定手机号</div>
        <div className="tip">
          <Assets name="notice" />
          微信登录成功!为更好的使用服务,请您绑定手机号和邮箱。
        </div>
        <SelectInput
          placeholder="请输入手机号"
          selectValue={this.state.data.area}
          select={MobileArea}
          value={this.state.data.mobile}
          error={this.state.mobileError}
          empty={emptyError.mobile}
          onSelect={value => {
            this.changeData('area', value);
            this.validMobile(false);
          }}
          onChange={e => {
            this.changeData('mobile', e.target.value);
            this.validMobile(false);
          }}
        />
        <VerificationInput
          placeholder="请输入验证码"
          value={this.state.data.mobileVerifyCode}
          error={this.state.validError}
          empty={emptyError.mobileVerifyCode}
          onSend={() => {
            return this.sendValid();
          }}
          onChange={e => {
            this.changeData('mobileVerifyCode', e.target.value);
            this.setState({ validError: '' });
          }}
        />
        {needEmail && (
          <DefaultInput
            placeholder="请输入邮箱"
            value={this.state.data.email}
            empty={emptyError.email}
            error={this.state.emailError}
            onChange={e => {
              this.changeData('email', e.target.value);
              this.validEmail();
            }}
          />
        )}
        {needEmail && (
          <div className="m-b-2">
            <RadioItem checked theme="white" className="m-r-5" />
            我已同意{' '}
            <a href={`/contract/${registerContract.key}`} target="_blank">
              《{registerContract.title}》
            </a>{' '}
            <a href={`/contract/${privacyContract.key}`} target="_blank">
              《{privacyContract.title}》
            </a>
            。
          </div>
        )}
        {this.state.mobileError && (
          <div className="m-b-2">
            <a className="f-r" onClick={() => this.changeType(LOGIN_PHONE)}>
              使用手机号码登录
            </a>
          </div>
        )}
        <Button
          type="primary"
          size="large"
          disabled={this.state.validError || this.state.mobileError}
          block
          onClick={() => {
            this.bind();
          }}
        >
          绑定
        </Button>
      </div>
    );
  }

  renderBindWx() {
    return (
      <div className="body">
        <div className="title">绑定微信号</div>
        <div className="tip">
          <Assets name="notice" />
          手机号注册成功!为更好的使用服务,建议您绑定微信号。
        </div>
        <div className="qr-code">
          <iframe
            key={this.state.scanNumber}
            frameBorder="0"
            src={`/login.html?appid=${WechatPcAppId}&redirectUri=${encodeURIComponent(PcUrl)}`}
            width="300"
            height="300"
          />
          <div className="text">请使用微信扫描二维码登录</div>
          <div
            className="jump"
            onClick={() => {
              this.close();
            }}
          >
            跳过
          </div>
        </div>
      </div>
    );
  }

  renderBindWxError() {
    return (
      <div className="body">
        <div className="title">绑定失败</div>
        <div className="text">该微信账户已绑定其他手机号码,您可直接扫码登入。</div>
        <div className="btn">
          <GButton
            radius
            onClick={() => {
              this.changeType(LOGIN_WX);
            }}
          >
            扫码登入
          </GButton>
        </div>
      </div>
    );
  }
}