// Learn cc.Class:
//  - https://docs.cocos.com/creator/manual/en/scripting/class.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

let _mat4_temp = cc.mat4();
let _vec2_temp = cc.v2();
let _vec2_temp2 = cc.v2();

export default cc.Class({
    extends: cc.TiledLayer,

    // 此处修改 增加firstTmxLayer参数
    _init(layerInfo, mapInfo, tilesets, textures, texGrids, tiledMap, firstTmxLayer) {
        // 修改结束
        this._cullingDirty = true;
        this._layerInfo = layerInfo;
        this._mapInfo = mapInfo;
        // 此处修改 保存firstTmxLayer参数
        this._firstTmxLayer = firstTmxLayer;
        this._tiledMap = tiledMap;
        // 修改结束

        let size = layerInfo._layerSize;

        // layerInfo
        this._layerName = layerInfo.name;
        this._tiles = layerInfo._tiles;
        this._properties = layerInfo.properties;
        this._layerSize = size;
        this._minGID = layerInfo._minGID;
        this._maxGID = layerInfo._maxGID;
        this._opacity = layerInfo._opacity;
        this._renderOrder = mapInfo.renderOrder;
        this._staggerAxis = mapInfo.getStaggerAxis();
        this._staggerIndex = mapInfo.getStaggerIndex();
        this._hexSideLength = mapInfo.getHexSideLength();
        this._animations = mapInfo.getTileAnimations();

        // tilesets
        this._tilesets = tilesets;
        // textures
        this._textures = textures;
        // grid texture
        this._texGrids = texGrids;

        // mapInfo
        this._layerOrientation = mapInfo.orientation;
        this._mapTileSize = mapInfo.getTileSize();

        let maptw = this._mapTileSize.width;
        let mapth = this._mapTileSize.height;
        let layerW = this._layerSize.width;
        let layerH = this._layerSize.height;

        if (this._layerOrientation === cc.TiledMap.Orientation.HEX) {
            // handle hex map
            const TiledMap = cc.TiledMap;
            const StaggerAxis = TiledMap.StaggerAxis;
            const StaggerIndex = TiledMap.StaggerIndex;
            let width = 0, height = 0;

            this._odd_even = (this._staggerIndex === StaggerIndex.STAGGERINDEX_ODD) ? 1 : -1;
            if (this._staggerAxis === StaggerAxis.STAGGERAXIS_X) {
                this._diffX1 = (maptw - this._hexSideLength) / 2;
                this._diffY1 = 0;
                height = mapth * (layerH + 0.5);
                width = (maptw + this._hexSideLength) * Math.floor(layerW / 2) + maptw * (layerW % 2);
            } else {
                this._diffX1 = 0;
                this._diffY1 = (mapth - this._hexSideLength) / 2;
                width = maptw * (layerW + 0.5);
                height = (mapth + this._hexSideLength) * Math.floor(layerH / 2) + mapth * (layerH % 2);
            }
            this.node.setContentSize(width, height);
        } else if (this._layerOrientation === cc.TiledMap.Orientation.ISO) {
            let wh = layerW + layerH;
            this.node.setContentSize(maptw * 0.5 * wh, mapth * 0.5 * wh);
        } else {
            this.node.setContentSize(layerW * maptw, layerH * mapth);
        }

        // offset (after layer orientation is set);
        this._offset = cc.v2(layerInfo.offset.x, -layerInfo.offset.y);
        this._useAutomaticVertexZ = false;
        this._vertexZvalue = 0;
        this._syncAnchorPoint();
        this._prepareToRender();
    },
    _updateCulling() {
        if (CC_EDITOR) {
            this.enableCulling(false);
        } else if (this._enableCulling) {
            // 此处修改 若不为首个layer 直接复用firstLayer的结果
            // this._firstTmxLayer不为空时 表示当前layer不是首个layer
            let firstTmxLayer = this._firstTmxLayer;
            if (!!firstTmxLayer) {
                this._cullingRect = firstTmxLayer._cullingRect;
                this._cullingDirty = firstTmxLayer._cacheCullingDirty;
                return;
            }
            // 修改结束

            this.node._updateWorldMatrix();
            cc.Mat4.invert(_mat4_temp, this.node._worldMatrix);
            let rect = cc.visibleRect;
            let camera = cc.Camera.findCamera(this.node);
            if (camera) {
                _vec2_temp.x = 0;
                _vec2_temp.y = 0;
                _vec2_temp2.x = _vec2_temp.x + rect.width;
                _vec2_temp2.y = _vec2_temp.y + rect.height;
                camera.getScreenToWorldPoint(_vec2_temp, _vec2_temp);
                camera.getScreenToWorldPoint(_vec2_temp2, _vec2_temp2);
                cc.Vec2.transformMat4(_vec2_temp, _vec2_temp, _mat4_temp);
                cc.Vec2.transformMat4(_vec2_temp2, _vec2_temp2, _mat4_temp);

                this._updateViewPort(_vec2_temp.x, _vec2_temp.y, _vec2_temp2.x - _vec2_temp.x, _vec2_temp2.y - _vec2_temp.y);
                // 此处修改 若为首个layer 缓存_cullingDirty。
                // _cullingDirty会在填充渲染数据后被改为false 所以需要缓存这里的结果
                if (!firstTmxLayer) {
                    this._cacheCullingDirty = this._cullingDirty;
                }
                // 修改结束
            }
        }
    },
    _traverseAllGrid () {
        let tiles = this._tiles;
        let texGrids = this._texGrids;
        let tilesetIndexArr = this._tilesetIndexArr;
        let tilesetIndexToArrIndex = this._tilesetIndexToArrIndex = {};

        const TiledMap = cc.TiledMap;
        const TileFlag = TiledMap.TileFlag;
        const FLIPPED_MASK = TileFlag.FLIPPED_MASK;

        let singleTexture = this._tiledMap.isSingleTexture();

        tilesetIndexArr.length = 0;
        for (let i = 0; i < tiles.length; i++) {
            let gid = tiles[i];
            if (gid === 0) continue;
            gid = ((gid & FLIPPED_MASK) >>> 0);
            let grid = texGrids[gid];
            if (!grid) {
                cc.error("CCTiledLayer:_traverseAllGrid grid is null, gid is:", gid);
                continue;
            }
            let tilesetIdx = grid.texId;
            if (tilesetIndexToArrIndex[tilesetIdx] !== undefined) continue;
            tilesetIndexToArrIndex[tilesetIdx] = tilesetIndexArr.length;
            tilesetIndexArr.push(tilesetIdx);
            
            // 此处修改 当只有一个图集时 可以直接停止遍历
            if (singleTexture) {
                break;
            }
            // 修改结束
        }
    },
});
