/**
 * @file        Textwindow component
 * @author      MicroMatrix <yangpan.1985@bytedance.com>
 * @copyright   2012-2020 bytedance
 * @link        git@code.byted.org:yangpan.1985/avg.git
 */

import React from 'react';
import core from 'core/core';
import createComponent from 'components/createComponent';
import ContainerMixin from 'components/ContainerMixin';
import NodeMixin from 'components/NodeMixin';
import PixiTextwindow from 'classes/TextWindow';
import pixiPropTypes from './pixi/propTypes';
import { Transition } from 'components/transition';
import transition from 'plugins/transition';

const RawTextwindow = createComponent('RawTextwindow', ContainerMixin, NodeMixin, {

  createNode() {
    this.node = new PixiTextwindow();
  },
  mountNode(props) {
     // color, opacity, width, height, x, y, etc.
    const layer = this.node;

    props.textRect && layer.setTextRectangle(props.textRect);
    props.xInterval != null && layer.setXInterval(props.xInterval);
    props.yInterval != null && layer.setYInterval(props.yInterval);
    props.bgFile && layer.setBackgroundFile(props.bgFile);
    props.opacity != null && layer.setOpacity(props.opacity);
    props.visible != null && layer.setVisible(props.visible);
    props.font && layer.setTextFont(props.font);
    props.size && layer.setTextSize(props.size);
    props.color != null && layer.setTextColor(props.color);
    props.bold != null && layer.setTextBold(props.bold);
    props.italic != null && layer.setTextItalic(props.italic);
    props.speed && layer.setTextSpeed(props.speed);
    props.text && layer.drawText(props.text, true);
    layer.x = props.x || 0;
    layer.y = props.y || 0;

    return layer;
  },
  updateNode(prevProps, props) {
    const layer = this.node;

    prevProps.textRect !== props.textRect && layer.setTextRectangle(props.textRect);
    prevProps.xInterval !== props.xInterval && layer.setXInterval(props.xInterval || 0);
    prevProps.yInterval !== props.yInterval && layer.setYInterval(props.yInterval || 0);
    prevProps.bgFile !== props.bgFile && layer.setBackgroundFile(props.bgFile);
    prevProps.opacity !== props.opacity && layer.setOpacity(props.opacity);
    prevProps.visible !== props.visible && layer.setVisible(props.visible);
    prevProps.font !== props.font && layer.setTextFont(props.font);
    prevProps.size !== props.size && layer.setTextSize(props.size);
    prevProps.color !== props.color && layer.setTextColor(props.color);
    prevProps.bold !== props.bold && layer.setTextBold(props.bold);
    prevProps.italic !== props.italic && layer.setTextItalic(props.italic);
    prevProps.speed !== props.speed && layer.setTextSpeed(props.speed);
    layer.x = props.x || 0;
    layer.y = props.y || 0;

  //  layer.setProperties(props);
  },

});

export class Textwindow extends React.Component {
  static displayName = 'Textwindow';
  static propTypes = pixiPropTypes;
  constructor(props) {
    super(props);

    this.handleScriptExec = this.handleScriptExec.bind(this);
    this.handleScriptTrigger = this.handleScriptTrigger.bind(this);
    this.handleArchiveSave = this.handleArchiveSave.bind(this);
    this.handleArchiveLoad = this.handleArchiveLoad.bind(this);

    this.transitionHandler = null;

    this.state = {
      props: {},
    };
  }
  componentWillMount() {
    this.setState({
      props: this.props,
      clickCallback: false,
      switchPageAfterClick: false,
      waitClick: false
    });
  }
  componentDidMount() {
    core.use('script-trigger', this.handleScriptTrigger);
    core.use('script-exec', this.handleScriptExec);
    core.use('save-archive', this.handleArchiveSave);
    core.use('load-archive', this.handleArchiveLoad);

    this.execute = transition(this.transLayer, this.execute.bind(this));
  }
  componentWillUnmount() {
    core.unuse('script-trigger', this.handleScriptTrigger);
    core.unuse('script-exec', this.handleScriptExec);
    core.unuse('save-archive', this.handleArchiveSave);
    core.unuse('load-archive', this.handleArchiveLoad);
  }
  async execute(ctx, next) {
    const { command, flags, params } = ctx;
    const layer = this.layer;
    let promise = Promise.resolve();
    let waitClick = false;
    let clickCallback = false;
    let switchPageAfterClick = false;

    if (command === 'r') {
      // waitClick = true;
      promise = layer.drawText('\n', false);
      clickCallback = true;
    } else if (command === 'l') {
      waitClick = true;
    } else if (command === 'p') {
      waitClick = true;
      // promise = layer.drawText('', true);
      clickCallback = true;
      switchPageAfterClick = true;
    } else if (flags.includes('clear')) {
      // layer.clearText();
      // it is a hack
      layer.drawText('', true);
    } else if (flags.includes('set')) {
      params.bgfile && (params.bgFile = params.bgfile);
      params.textrect && (params.textRect = params.textrect);
      params.xinterval != null && (params.xInterval = params.xinterval);
      params.yinterval != null && (params.yInterval = params.yinterval);
      this.setState({
        props: Object.assign({}, this.state.props, params),
      });
    } else if (flags.includes('reset')) {
      this.setState({
        props: this.props,
      });
    } else if (flags.includes('show')) {
      layer.setVisible(true);
    } else if (flags.includes('hide')) {
      this.reshowWhenScriptTrigger = flags.includes('soft');
      layer.setVisible(false);
    } else if (flags.includes('continue')) {
      waitClick = true;
      promise = layer.drawText(params.text, false);
      clickCallback = true;
    } else {
      waitClick = false;
      promise = layer.drawText(params.text, false);
      clickCallback = true;
    }
    this.state.clickCallback = clickCallback;
    this.state.switchPageAfterClick = switchPageAfterClick;
    ctx.break = waitClick;
    await ((flags.includes('nowait') || flags.includes('_skip_')) ? Promise.resolve() : promise);
    if (flags.includes('_skip_')) {
      await this.layer.completeText();
    }
    this.state.clickCallback = false;
    await next();
  }
  async handleScriptTrigger(ctx, next) {
    const layer = this.layer;

    if (!layer.visible && this.reshowWhenScriptTrigger) {
      layer.setVisible(true);

      return;
    }
    if (this.state.switchPageAfterClick) {
      await this.layer.drawText('', true);
      this.state.switchPageAfterClick = false;
    }
    if (this.state.clickCallback) {
      this.layer.completeText();
      this.state.clickCallback = false;
    } else {
      await next();
    }
  }
  async handleScriptExec(ctx, next) {
    if (['text', 'r', 'l', 'p', '*'].includes(ctx.command)) {
      if (typeof ctx.params.raw === 'string') {
        ctx.params.text = ctx.params.raw;
      }
      await this.execute(ctx, next);
    } else {
      await next();
    }
  }
  async handleArchiveSave(ctx, next) {
    const layer = this.layer;

    ctx.data.textwindow = { props: { ...this.state.props, children: null }, text: layer.text, children: null, switchPageAfterClick: this.state.switchPageAfterClick };
    await next();
  }
  async handleArchiveLoad(ctx, next) {
    const { props, text, children, switchPageAfterClick } = ctx.data.textwindow;

    this.setState({
      props: {
        ...this.props,
        ...props,
        text,
        children
      },
      switchPageAfterClick
    });
    const layer = this.layer;

    layer.setVisible(true);
    layer.drawText(ctx.data.textwindow.text, true);
    // layer.completeText();
    await next();
  }
  render() {
    return (
      <Transition ref={transLayer => (this.transLayer = transLayer)}>
        <RawTextwindow {...this.state.props} ref={layer => (this.layer = layer)}>
          {this.props.children}
        </RawTextwindow>
      </Transition>
    );
  }
}

// module.exports = Textwindow;
