import { EventDispatcher } from "../events/EventDispatcher";
import { CanvasGraphicsRenderer } from "./plugins/CanvasGraphicsRenderer";
import { Container, DisplayObject } from "../display";
import CanvasMaskManager from "./managers/CanvasMaskManager";
import CanvasSpriteRenderer from "./plugins/CanvasSpriteRenderer";
import { RENDERER_TYPE, BLEND_MODES } from "../const";
import RenderTexture from "../texture/RenderTexture";
import { Matrix } from "../math";
import { SystemRenderer } from "./SystemRenderer";
import CanvasRenderTarget from "./renderTarget/CanvasRenderTarget";
import { mapCanvasBlendModes } from "../utils";


/**
 * 暂时不用，用时再说
 */
export class CanvasRenderer extends SystemRenderer {
  /**
   * 主屏幕渲染上下文
   */
  rootContext: CanvasRenderingContext2D;
  /**
   * 当前使用的上下文
   */
  context: CanvasRenderingContext2D;
  /**
   * 遮罩管理类
   */
  maskManager: CanvasMaskManager;
  /**
   * 插件，暂时只有图形和图片的
   */
  plugins;

  /**
   * 当前使用的混色模式
   */
  _activeBlendMode: BLEND_MODES;
  /**
   * 是否影响外部混色
   */
  _outerBlend: boolean;
  /**
   * 所有对应值
   */
  private blendModes: any;

  constructor(context: CanvasRenderingContext2D, width: number, height: number) {
    super();
    this.type = RENDERER_TYPE.CANVAS
    this._instanceType = "CanvasRenderer";

    this.rootContext = context;

    this.maskManager = new CanvasMaskManager(this);

    // this.initPlugins();
    this.plugins = {
      sprite: null,
      graphics: null,
    }
    this.plugins.sprite = new CanvasSpriteRenderer(this);
    this.plugins.graphics = new CanvasGraphicsRenderer(this);

    this.blendModes = mapCanvasBlendModes();
    this._activeBlendMode = null;
    this._outerBlend = false;

    //
    this.resize(width, height)
  }

  /**
   * 渲染方法
   * @param {DisplayObject} displayObject - 渲染对象
   * @param {RenderTexture} [renderTexture] -离屏渲染纹理
   * @param {Matrix} [transform] - 矩阵偏移
   */
  render(displayObject: DisplayObject, renderTexture?: any/*RenderTexture*/, transform?: Matrix) {

    //渲染开始前触发
    this.dispatchEvent('prerender');

    //是否渲染到主屏幕
    let renderingToScreen = !renderTexture;
    if (renderTexture) {
      renderTexture = renderTexture.baseTexture || renderTexture;
      if (!renderTexture._canvasRenderTarget) {
        renderTexture._canvasRenderTarget = new CanvasRenderTarget(
          renderTexture.width,
          renderTexture.height,
        );
        renderTexture.source = renderTexture._canvasRenderTarget.canvas;
        renderTexture.valid = true;
      } else {
        //已有的话，需要重画
        renderTexture._canvasRenderTarget.clear();
        renderTexture._canvasRenderTarget.resize(renderTexture.width, renderTexture.height);
      }
      //当前上下文要修改成离屏的
      this.context = renderTexture._canvasRenderTarget.context;
    } else {
      //当前上下文就是根节点的
      this.context = this.rootContext;
    }

    const context = this.context;

    if (!renderTexture) {
      this._lastObjectRendered = displayObject;
    }

    //update更新属性
    displayObject.update()

    //存下真实的父级对象
    const cacheParent = displayObject.parent;
    const tempWt = this._tempDisplayObjectParent.transform.worldMatrix;

    if (transform) {
      //有transform则复制
      tempWt.copy(transform);
      //标记要更新transform
      this._tempDisplayObjectParent.transform._worldID = -1;
    }
    else {
      //没有就初始化
      tempWt.identity();
    }

    displayObject.parent = this._tempDisplayObjectParent;

    displayObject.updateTransform();

    displayObject.parent = cacheParent;

    //初始化上下文状态
    context.save();
    context.setTransform(1, 0, 0, 1, 0, 0);
    context.globalAlpha = 1;

    //默认模式
    this._activeBlendMode = BLEND_MODES.NORMAL;
    this._outerBlend = false;
    context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL];

    // context.clearRect(0, 0, this.width, this.height);
    if (renderingToScreen) {
      if (this.transparent) {
        context.clearRect(0, 0, this.width, this.height);
      }
      else {
        context.fillStyle = this._backgroundColorString;
        context.fillRect(0, 0, this.width, this.height);
      }
    }

    //执行绘制
    displayObject.renderCanvas(this);

    // context["draw"]();

    context.restore();

    //渲染后触发
    this.dispatchEvent('postrender');
  }

  /**
   * 清空画布
   */
  // clear(clearColor: string) {
  //   const context = this.context;
  //   clearColor = clearColor || this._backgroundColorString;
  //   if (!this.transparent && clearColor) {
  //     context.fillStyle = clearColor;
  //     context.fillRect(0, 0, this.width, this.height);
  //   }
  //   else {
  //     context.clearRect(0, 0, this.width, this.height);
  //   }
  // }

  /**
   * Sets the blend mode of the renderer.
   *
   * @param {number} blendMode - See {@link PIXI.BLEND_MODES} for valid values.
   * @param {boolean} [readyForOuterBlend=false] - Some blendModes are dangerous, they affect outer space of sprite.
   * Pass `true` only if you are ready to use them.
   */
  setBlendMode(blendMode: BLEND_MODES, readyForOuterBlend: boolean = false) {
    const outerBlend = blendMode === BLEND_MODES.SRC_IN
      || blendMode === BLEND_MODES.SRC_OUT
      || blendMode === BLEND_MODES.DST_IN
      || blendMode === BLEND_MODES.DST_ATOP;

    if (!readyForOuterBlend && outerBlend) {
      blendMode = BLEND_MODES.NORMAL;
    }

    if (this._activeBlendMode === blendMode) {
      return;
    }

    this._activeBlendMode = blendMode;
    this._outerBlend = outerBlend;
    this.context.globalCompositeOperation = this.blendModes[blendMode];
  }

  /**
   * 销毁
   */
  destroy() {
    this.destroyPlugins();

    super.destroy();

    this.context = null;

    this.maskManager.destroy();
    this.maskManager = null;
  }

  destroyPlugins() {
    this.plugins.sprite.destroy();
    this.plugins.graphics.destroy();
  }
}

