import { Group } from '../util/graphic';
import { isObject, isArray, each, enableClassManagement, merge } from '../util';
import ShapeStorage from '../util/ShapeStorage';
import { translate, scale } from 'zrender/src/core/matrix';
import { viewActions } from '../action/event.js';

const TYPE = 'view';

/**
 * View基类
 * 
 * @class View
 * @extends {ShapeStorage}
 */
class View extends ShapeStorage {

    static type = TYPE;

    type = TYPE;

    _lastUpdateTag = undefined; // 上次更新的tag,避免不必要的渲染

    constructor(model, globalModel, global) {
        super(...arguments);

        this.setRoam(model, globalModel, global);
    }

    zoomable(model, globalModel, global) {
        let roam = model.get('roam') || {};
        let isRoam = !roam.enable;

        model.set({
            roam: {
                enable: isRoam,
            }
        });
    }

    /**
     * 设置roam
     * 
     * @param {Object} model 
     * @param {Object} globalModel
     * @param {Object} global 
     * @private
     */
    setRoam(model, globalModel, global) {
        let roam = model.get('roam') || {};
        let globalRoam = globalModel.get('roam');

        merge(roam, globalRoam);

        let gridModel;

        if (roam.inGrid) {
            let gridIndex = model.get('$gridIndex');

            gridModel = globalModel.getComponentByIndex('grid', gridIndex)
        }

        global.on('mousewheel', ({ offsetX, offsetY, wheelDelta }) => {
            if ((!gridModel || gridModel.isPointInGrid(offsetX, offsetY)) && roam.enable) {
                this.scale(offsetX, offsetY, wheelDelta);
            }
        });

        this._roaming = false;
        let startX, startY, startPosition;

        global.on('mousedown', ({ offsetX, offsetY, target }) => {
            if ((!gridModel || gridModel.isPointInGrid(offsetX, offsetY)) && roam.enable) {
                let group = this.group;

                if (!group || (!roam.onTarget && target)) return;

                this._roaming = true;
                startX = offsetX;
                startY = offsetY;
                startPosition = [group.position[0], group.position[1]];
            }
        });

        global.on('mousemove', ({ offsetX, offsetY }) => {
            if (this._roaming) {
                let group = this.group;

                group.attr({
                    position: [startPosition[0] + (offsetX - startX), startPosition[1] + (offsetY - startY)]
                });
            }
        });

        global.on('mouseup', (e) => {
            this._roaming = false;
        });

        this.roam = roam;
    }

    /**
     * 缩放view
     * 
     * @param {number} offsetX 缩放中线点X
     * @param {number} offsetY 缩放中心点Y
     * @param {number} wheelDelta 缩放比例
     */
    scale(offsetX, offsetY, wheelDelta) {
        let group = this.group;
        if (!group) return;
        let scaleDelta = wheelDelta * 0.1 + 1;
        let transform = group.getLocalTransform();

        translate(transform, transform, [-offsetX, -offsetY]);
        scale(transform, transform, [scaleDelta, scaleDelta]);
        translate(transform, transform, [offsetX, offsetY]);

        group.transform = transform;
        group.decomposeTransform();
        group.dirty();
    }

    /**
     * 内部实际进行render方法,在外部render方法进行一些包装
     * 
     * @param {Object} model 
     * @param {Object} globalModel
     * @param {Object} global 
     * @private
     */
    __render(model, globalModel, global) {
        if (this._lastUpdateTag !== model._updateTag) { // 与上次更新的tag比较
            //console.log(`${model.type}_${model.index}视图更新了!`);
            this.render(model, globalModel, global);
            this._lastUpdateTag = model._updateTag;

            if (model.get('enableEdit')) {
                this.renderEdit(model, globalModel, global);
            } else {
                this.removeEdit();
            }

            global.dispatchAction(model, viewActions.didRender, { model: model, view: this });
        }
    }

    /**
     * 渲染函数
     * 
     * @param {Object} model 
     * @param {Object} globalModel
     * @param {Object} global 
     */
    render(model, globalModel, global) {
    }

    /**
     * 编辑状态渲染函数
     * 
     * @param {Object} model 
     * @param {Object} globalModel
     * @param {Object} global 
     * 
     */
    renderEdit(model, globalModel, global) {
    }

    /**
     * 移除edit状态相关图形
     * 
     * @param {Object} model 
     * @param {Object} globalModel
     * @param {Object} global 
     */
    removeEdit() {
        this.eachShape((shape, name) => {
            if (name.indexOf('_edit_') === 0) {
                shape.disableDrag && shape.disableDrag();
                this.removeShape(name);
            }
        });
    }

    /**
     * 移除view内所有图形
     */
    remove() {
        super.remove(...arguments);
    }
}

export default enableClassManagement(View);