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


/**
 * @class
 * @extends SystemRenderer
 */
export default class CanvasRenderer extends SystemRenderer {
    /**
     * 主屏幕渲染上下文
     */
    rootContext: CanvasRenderingContext2D;
    /**
     * 当前使用的上下文
     */
    context: CanvasRenderingContext2D;
    /**
     * 遮罩管理类
     */
    maskManager: CanvasMaskManager;
    /**
     * 考虑是否需要支持
     */
    smoothProperty: string;
    /**
     * 插件，暂时只有图形和图片的
     */
    plugins: { sprite: CanvasSpriteRenderer; graphics: CanvasGraphicsRenderer; };
    renderingToScreen: boolean;

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



    constructor(options: RendererOptions) {
        super(options);
        this._instanceType = "CanvasRenderer";
        this.type = RENDERER_TYPE.CANVAS;
        this.rootContext = this.htmlElement ? this.htmlElement.getContext('2d', { alpha: this.transparent }) : null;
        this.context = this.rootContext;

        this.maskManager = new CanvasMaskManager(this);

        //smooth兼容
        this.smoothProperty = 'imageSmoothingEnabled';
        if (this.rootContext && !this.rootContext.imageSmoothingEnabled) {
            if (this.rootContext["webkitImageSmoothingEnabled"]) {
                this.smoothProperty = 'webkitImageSmoothingEnabled';
            }
            else if (this.rootContext["mozImageSmoothingEnabled"]) {
                this.smoothProperty = 'mozImageSmoothingEnabled';
            }
            else if (this.rootContext["oImageSmoothingEnabled"]) {
                this.smoothProperty = 'oImageSmoothingEnabled';
            }
            else if (this.rootContext["msImageSmoothingEnabled"]) {
                this.smoothProperty = 'msImageSmoothingEnabled';
            }
        }

        // 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.renderingToScreen = false;

    }

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

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

        //是否渲染到主屏幕
        this.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];

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

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

        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.htmlElement.width, this.htmlElement.height);
        }
        else {
            context.clearRect(0, 0, this.htmlElement.width, this.htmlElement.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;

        this.smoothProperty = null;
    }

    /**
     * 缩放尺寸
     * @param {number} screenWidth 
     * @param {number} screenHeight
     */
    resize(screenWidth: number, screenHeight: number) {
        super.resize(screenWidth, screenHeight);

        if (this.smoothProperty) {
            this.rootContext[this.smoothProperty] = true;
        }
    }

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

