import * as React from 'react'

import { openAppLofter } from 'nw-app-lofter'
import { isLofter } from 'nw-detect';

import { parse } from 'query-string-for-all';

import { callHandler } from 'nejsbridge/dist/bridge.lofter.es';

import {
  Props,
  State
} from './type'

import { Popup } from '../common/popup';
import { Tabs, TabPane } from '../common/tabs';
import AddressModal from './address-modal';
import { 
  MissionTitle,
  MissionList,
  MissionDesc,
} from './missions';
import {
  AwardList,
} from './awards'

import { showMessage } from '../common/toast/toast'
import { InfoIcon, ClockIcon } from '../common/icons'
import { goToLogin } from '../utils/login';
import { formatMonthDate, formatFullDate } from '../utils/format';
import localParam from '../utils/localParam';
import log from '../utils/lofter-log'
import { appNavigate } from '../utils/navigate'
import { isCardChannel } from '../utils/card-utils';
import { fetchTotalMission, convertSimplePrize } from './actions';
import { BaseComponent } from '../base-component'


import * as Styled from './index.style'

const urlData = parse(location.search);
const { rem } = Styled;

interface InfoBlockProps {
  points: number,
  text: string,
  icon: string,
  color?: string,
}
export class InfoBlock extends React.Component<InfoBlockProps> {
  render() {
    const { points, text, icon, color } = this.props;
    return (
      <Styled.InfoBlock color={color}>
        <ClockIcon className="clock" />
        <span className="text">{text}</span>
        <span className="points">
          <img src={icon} alt="图标" className="icon" />
          x{points}
        </span>
      </Styled.InfoBlock>
    )
  }
}

export class CardMission extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    const urlData = localParam();
    if (urlData.mission === 'true' || props.alwaysShow) {
      if (isLofter() || isCardChannel) {
        // 站内或渠道内，允许做任务
        this.state.showMissionPopup = true;
      } else if (!this.props.isEdit){
        this.openApp();
      }
    }
  }

  static defaultProps = new Props()

  state = new State()

  missionScrollRef: HTMLElement;
  awardScrollRef: HTMLElement;

  // missionCode: string;
  // awardCode: string;

  awardAddressData: {
    activityCode: string,
    prizeActivityCode: string,
    prizeCode: string,
  }

  dataRequestTime: number = 0;

  getData = async ({
    time,
    callback,
  } : {
    time?: number,
    callback?: () => void
  } = {}) => {
    try {
      const res = await fetchTotalMission(this.props.activityCode, time);
      if (res.code === 200) {
        this.setState({
          isLogin: true,
          points: res.data.points,
          pointsIcon: res.data.pointsIcon,
          missionData: res.data.missionActivity,
          awardData: res.data.awardActivity,
          hintMissionStatus: res.data.hintMissionStatus,
        }, () => {
          callback && callback();
        })
      } else {
        if (res.code !== 401) {
          showMessage({
            text: res.msg
          })
        }
      }
      console.log('activity data', time, res);
    } catch (error) {
      console.log('Get data failed', error)
      showMessage('活动太火爆了，请稍后再来哦~')
    }
  }

  openApp = () => {
    openAppLofter({
      path: 'webview',
      query: {
        url: location.href
      }
    })
  }

  checkAppAndLogin = (type: 'mission' | 'award', callback: () => void) => {
    if (window.location.host.indexOf('cms-yaolu.hz.netease.com') >= 0){
      callback();
      return;
    }
    // 如果站外，并且不是渠道，直接唤起app才能做任务
    if (!isLofter() && !isCardChannel) {
      this.openApp();
      return;
    }
    if (type === 'mission') {
      if (this.state.missionData && this.state.missionData.activityStatus === -1) {
        showMessage('活动还没开始哦~')
        return;
      }
      if (this.state.missionData && this.state.missionData.activityStatus === 1) {
        showMessage('活动已经结束啦~')
        return;
      }
    }

    if (type === 'award') {
      if (this.state.awardData && this.state.awardData.status === -1) {
        showMessage('活动还没开始哦~')
        return;
      }
      if (this.state.awardData && this.state.awardData.status === 1) {
        showMessage('活动已经结束啦~')
        return;
      }
    }
    
    if (!this.state.isLogin) {
      goToLogin(() => {
        this.getData({
          time: new Date().getTime(),
          callback
        });
      }, 'card')
      return;
    }
    // 为了兼容5.1设备不支持visibility api，每次拉起弹窗都更新一次数据
    this.getData({
      time: new Date().getTime(),
    });
    callback();
  }

  showMissionPopup = () => {
    log.capture(`card-mission-click`, {
      category: 'cmsact',
      action: 0,
      scene: 'cmsact',
      v: '1.0.0'
    })
    this.checkAppAndLogin('mission', () => {
      if (!this.state.missionData || !this.state.missionData.tabList) {
        showMessage('活动太火爆了，请稍后再来哦~')
        return;
      }
      this.setState({
        showMissionPopup: true
      })
    })
  }

  hideMissionPopup = () => {
    this.setState({
      showMissionPopup: false
    })
  }

  missionMaskClick = () => {
    const { alwaysShow, maskClickTarget, isEdit } = this.props;
    if (isEdit) return;
    if (alwaysShow) {
      if (maskClickTarget) {
        if (maskClickTarget.startsWith('https://www.lofter.com/market/fe/html/cardHome.html') && urlData.from === 'cardHome'){
          callHandler('njb_closeCurrentWebview');
        } else {
          appNavigate(maskClickTarget);
        }
      }
      return;
    };
    this.hideMissionPopup();
  }

  showAwardPopup = () => {
    log.capture(`card-award-click`, {
      category: 'cmsact',
      action: 0,
      scene: 'cmsact',
      v: '1.0.0'
    })
    this.checkAppAndLogin('award', () => {
      if (!this.state.awardData || !this.state.awardData.items) {
        showMessage('活动太火爆了，请稍后再来哦~')
        return;
      }
      this.setState({
        showAwardPopup: true
      })
    })
  }

  hideAwardPopup = () => {
    this.setState({
      showAwardPopup: false
    })
  }

  awardMaskClick = () => {
    const { alwaysShow, maskClickTarget } = this.props;
    if (alwaysShow) {
      if (maskClickTarget) {
        if (maskClickTarget.startsWith('https://www.lofter.com/market/fe/html/cardHome.html') && urlData.from === 'cardHome'){
          callHandler('njb_closeCurrentWebview');
        } else {
          appNavigate(maskClickTarget);
        }
      }
      return;
    };
    this.hideAwardPopup();
  }

  showAddressModal = ({
    activityCode,
    prizeActivityCode,
    prizeCode,
  } :{
    activityCode: string,
    prizeActivityCode: string,
    prizeCode: string,
  }) => {
    this.awardAddressData = {
      activityCode,
      prizeActivityCode,
      prizeCode
    };
    this.setState({
      showAddressModal: true,
    })
  }

  hideAddressModal = () => {
    this.awardAddressData = {
      activityCode: '',
      prizeActivityCode: '',
      prizeCode: ''
    };
    this.setState({
      showAddressModal: false,
    })
  }

  submitAddressPrize = (data: any, callback?: () => void) => {
    console.log('submitAddressPrize', data);
    if (!this.awardAddressData || !this.awardAddressData.activityCode || !this.awardAddressData.prizeCode) {
      console.warn('No award adress data preset');
      return;
    }
    convertSimplePrize({
      addressId: data.addressId,
      activityCode: this.awardAddressData.activityCode,
      prizeActivityCode: this.awardAddressData.prizeActivityCode,
      prizeCode: this.awardAddressData.prizeCode,
    }).then(() => {
      this.hideAddressModal();
      this.getData({
        time: new Date().getTime(),
      });
      callback && callback();
    })
  }

  monitorVisibility = () => {
    if (this.props.isEdit) return;
    const handleVisibilitychange = () => {
      if (!document.hidden) {
        console.log('monitorVisibility update', new Date().getTime());
        this.getData({
          time: new Date().getTime(),
        });
      }
    };
    document.addEventListener('visibilitychange', handleVisibilitychange);
  }

  loadFont = () => {
    const { point : { font } } = this.props
    if (font) {
      const style = document.createElement('style');
      style.innerText = `@font-face {
        font-family: "Point Font";
        src: url("${font}") format("truetype");
      }`;
      document.head.appendChild(style);
    }
  }

  static getDerivedStateFromProps(props: Props, state: State) {
    if (props.alwaysShow && !state.showMissionPopup) {
      return {
        showMissionPopup: true,
      }
    }
    return null;
  }

  componentDidMount() {
    // if (this.props.isEdit) {
    //   this.watch()
    // }
    this.loadFont();
    this.monitorVisibility();
    this.getData({
      time: new Date().getTime(),
    });
  }

  watch = () => {
    let el = document.getElementById('viewport-left')
    let vwEl = document.getElementById('viewport')
    let left = vwEl.getBoundingClientRect().left
    this.setState({
      viewportLeft: left
    })
    const config = { attributes: true, childList: true}
    const callback = (mutationList: any) => {
      mutationList.forEach((mutation: any) => {
        switch(mutation.type) {
          case 'childList':
            this.setState({
              viewportLeft: vwEl.getBoundingClientRect().left
            })
            break;
        }
      })
    }
    let observer = new MutationObserver(callback)
    observer.observe(el, config)
  }

  triggerMission = () => {
    log.capture(`card-award-mission-click`, {
      category: 'cmsact',
      action: 0,
      scene: 'cmsact',
      v: '1.0.0'
    })
    this.hideAwardPopup();
    this.showMissionPopup();
  }

  triggerAward = () => {
    log.capture(`card-mission-award-click`, {
      category: 'cmsact',
      action: 0,
      scene: 'cmsact',
      v: '1.0.0'
    })
    this.hideMissionPopup();
    this.showAwardPopup();
  }

  goRule = () => {
    const { ruleUrl, isEdit } = this.props;
    if (ruleUrl && !isEdit) {
      appNavigate(ruleUrl);
    }
  }

  render() {
    const {
      activityCode,
      style,
      isEdit,
      mission,
      dot,
      award,
      point,
      missionPanel,
      awardPanel,
      previewMission,
      previewAward,
      previewAddress,
      mainColor = '#000',
      combinedBackground,
      addressModal,
      ruleMarginLeft,
      missionRuleTop,
      awardRuleTop,
      alwaysShow,
    } = this.props
    const {
      viewportLeft,
      missionData,
      awardData,
      points,
      pointsIcon,
      hintMissionStatus,
    } = this.state;

    let {
      showMissionPopup,
      showAwardPopup,
      showAddressModal,
    } = this.state;

    if (isEdit && previewMission) {
      showMissionPopup = true
    }
    if (isEdit && previewAward) {
      showAwardPopup = true
    }
    if (isEdit && previewAddress) {
      showAddressModal = true
    }

    return (
      <div 
        style={{
          ...style,
        }}
        // 修复 safari 下编辑器无法显示 position：fixed 的按钮
        // ref={(node) => {
        //   if (node) {
        //     node.style.setProperty("z-index", "auto", "important");
        //   }
        // }}
      >
        <BaseComponent {...this.props}>
          {!alwaysShow && <Styled.MissionContainer isEdit={isEdit} dot={dot}>
            <div 
              id="missionBtn" 
              style={{
                width: mission.width + 'rem',
                height: mission.height + 'rem',
                left: mission.left + 'rem',
                top: mission.top + 'rem',
              }}
              className={hintMissionStatus === 0 ? 'hint' : ''} 
              onClick={this.showMissionPopup}
            >任务热区</div>
            <div 
              id="awardBtn"
              style={{
                width: award.width + 'rem',
                height: award.height + 'rem',
                left: award.left + 'rem',
                top: award.top + 'rem',
              }}
              onClick={this.showAwardPopup}
            >兑换热区</div>
            <div 
              id="points"
              style={{
                width: point.width + 'rem',
                height: point.height + 'rem',
                lineHeight: point.height + 'rem',
                left: point.left + 'rem',
                top: point.top + 'rem',
                fontSize: point.fontSize + 'rem',
                color: point.color,
              }}
              >
              {points}
            </div>
          </Styled.MissionContainer>}
          <Popup background={combinedBackground} gapWidth="0" isEdit={isEdit} show={showMissionPopup} close={this.missionMaskClick} scrollRef={this.missionScrollRef}>
            <Styled.RuleBtn onClick={this.goRule} left={ruleMarginLeft} top={missionRuleTop} color="#B3B3B3">规则<InfoIcon className="icon" /></Styled.RuleBtn>
            {(missionPanel.topGap && typeof missionPanel.topGap === 'number') ? <Styled.Gap style={{height: `${missionPanel.topGap}rem`}}></Styled.Gap> : null}
            <Styled.PopContent>
              {missionPanel.titleImage && missionPanel.titleImage.url && <MissionTitle image={missionPanel.titleImage.url} />}
              <Tabs navStyle={{ margin: `${rem(24)} ${rem(32)} 0` }} defaultValue={0} ref={(ref: HTMLElement) => {
                this.missionScrollRef = ref
              }} color={mainColor}>
                {
                  missionData && missionData.tabList && missionData.tabList.map((tab, index) => {
                    return (
                      <TabPane key={index} title={tab.tabName} value={index}>
                        <InfoBlock 
                          text={`${formatFullDate(missionData.activityEndTime)}结束`}
                          points={points}
                          color="#C6BA88"
                          icon={pointsIcon}
                        />
                        <MissionDesc 
                        color="#2E2E2E" 
                        // points={points}
                        // icon={missionData.pointsIcon}
                        >
                          {tab.tabDesc}
                        </MissionDesc>
                        <MissionList
                          isEdit={isEdit}
                          activityCode={activityCode}
                          color={mainColor}
                          list={tab.missionInfoList}
                          missionData={missionData}
                          pointsIcon={pointsIcon}
                          refreshData={this.getData}
                        />
                      </TabPane>
                    )
                  })
                }
              </Tabs>              
            </Styled.PopContent>
            {
              missionPanel && (missionPanel.triggerImage && missionPanel.triggerImage.url || missionPanel.triggerText) && <Styled.TriggerBtn 
                backgroundImage={missionPanel.triggerImage.url}
                onClick={this.triggerAward}
                color={mainColor}
              >
                {missionPanel.triggerText}
              </Styled.TriggerBtn>
            }
          </Popup>
          <Popup background={combinedBackground} gapWidth="0" isEdit={isEdit} height="90%" show={showAwardPopup} close={this.awardMaskClick} scrollRef={this.awardScrollRef}>
            <Styled.RuleBtn onClick={this.goRule} left={ruleMarginLeft} top={awardRuleTop} color="#B3B3B3">规则<InfoIcon className="icon" /></Styled.RuleBtn>
            {(awardPanel.topGap && typeof awardPanel.topGap === 'number') ? <Styled.Gap style={{height: `${awardPanel.topGap}rem`}}></Styled.Gap> : null}
            <Styled.PopContent>
              {awardPanel.titleImage && awardPanel.titleImage.url && <MissionTitle image={awardPanel.titleImage.url} />}
              {
                awardData && <InfoBlock 
                  text={`兑换时间：${formatMonthDate(awardData.startTime)}-${formatMonthDate(awardData.endTime)}`}
                  points={points}
                  color="#C6BA88"
                  icon={pointsIcon}
                />
              }
              {
                awardData && <AwardList
                  ref={(ref: HTMLElement) => {
                    this.awardScrollRef = ref
                  }}
                  color={mainColor}
                  list={awardData.items}
                  points={points}
                  pointsIcon={pointsIcon}
                  awardData={awardData}
                  activityCode={activityCode}
                  refreshData={this.getData}
                  showAddressModal={this.showAddressModal}
                />
              }
            </Styled.PopContent>
            {
              awardPanel && <Styled.TriggerBtn 
                backgroundImage={awardPanel.triggerImage.url}
                onClick={this.triggerMission}
                color={mainColor}
              >
                {awardPanel.triggerText}
              </Styled.TriggerBtn>
            }
            <AddressModal 
              show={showAddressModal} 
              onCancel={this.hideAddressModal} 
              onOk={this.submitAddressPrize}
              background={combinedBackground}
              color={mainColor}
              buttonImage={addressModal.buttonImage}
              isEdit={isEdit}
            />
          </Popup>
        </BaseComponent>
      </div>
    )
  }
}