import Apple from "./Apple";
import Brick from "./Brick";
import DataLevel from "./DataLevel";
import { TYPEMAP } from "./NodeType";
import Saw from "./Saw";
import Stone from "./Stone";
import Trap from "./Trap";

const { ccclass, property } = cc._decorator;

@ccclass
export default class MapLevel extends cc.Component {

    mapWall: number[][] = [];
    listApple: { x: number, y: number, type: number, obj: Apple }[] = [];
    listSaw: { x: number, y: number, type: number, obj: Saw }[] = [];
    listTrap: { x: number, y: number, type: number, obj: Trap }[] = [];
    listStone: { x: number, y: number, type: number, obj: Stone }[] = [];
    posHoleEnd: { x: number, y: number, type: number } = null;

    listSpWall: cc.SpriteFrame[] = [];
    trap: cc.Prefab = null;
    saw: cc.Prefab = null;
    holeEnd: cc.Prefab = null;
    apple: cc.Prefab = null;
    stone: cc.Prefab = null;
    sizeMap: number = null;
    offsetMap: number = null;
    stoneSF: cc.SpriteFrame = null;
    appleSF: cc.SpriteFrame = null;
    is18: boolean = true;

    generateMapByLevel(dataLevel: DataLevel, listSpWall: cc.SpriteFrame[], stoneSF: cc.SpriteFrame, appleSF: cc.SpriteFrame, trap: cc.Prefab, saw: cc.Prefab, holeEnd: cc.Prefab, apple: cc.Prefab, stone: cc.Prefab, sizeMap: number, offsetMap: number, is18: boolean) {
        this.listSpWall = listSpWall;
        this.trap = trap;
        this.saw = saw;
        this.holeEnd = holeEnd;
        this.apple = apple;
        this.stone = stone;
        this.stoneSF = stoneSF;
        this.appleSF = appleSF;
        this.sizeMap = sizeMap;
        this.offsetMap = offsetMap;
        this.is18 = is18;
        this.mapWall = [];
        for (let y = 0; y < dataLevel.height; y++) {
            this.mapWall.push([]);
            for (let x = 0; x < dataLevel.width; x++) {
                this.mapWall[y].push(TYPEMAP.EMPTY);
            }
        }
        let count = dataLevel.bricks.length;
        for (const brick of dataLevel.bricks) {
            let brickNode: cc.Node = this.instanceNodeById(brick);
            if (brickNode != null) {
                brickNode.zIndex = count--;
            }
        }
    }

    instanceNodeById(brickData: Brick): cc.Node {
        let node: cc.Node = null;
        switch (brickData.id) {
            case TYPEMAP.WALL:
                let brick = new cc.Node();
                brick.name = "wall_" + brickData.id;
                brick.parent = this.node;
                brick.addComponent(cc.Sprite);
                if (brickData.index) {
                    brick.getComponent(cc.Sprite).spriteFrame = this.listSpWall[brickData.index];
                } else {
                    brick.getComponent(cc.Sprite).spriteFrame = this.listSpWall[12];
                }
                brick.width = this.sizeMap;
                brick.height = this.sizeMap;
                brick.position = cc.v3(this.offsetMap * brickData.x, this.offsetMap * brickData.y);
                this.mapWall[brickData.y][brickData.x] = TYPEMAP.WALL;
                node = brick;
                break;
            case TYPEMAP.STONE:
                let stone: cc.Node = cc.instantiate(this.stone);
                stone.parent = this.node;
                stone.addComponent(cc.Sprite).spriteFrame = this.stoneSF;
                stone.width = this.offsetMap;
                stone.height = this.offsetMap;
                stone.position = cc.v3(this.offsetMap * brickData.x, this.offsetMap * brickData.y);
                node = stone;
                this.listStone.push({
                    x: brickData.x,
                    y: brickData.y,
                    type: TYPEMAP.STONE,
                    obj: stone.getComponent(Stone),
                })
                break;
            case TYPEMAP.TRAP:
                let trap: cc.Node = cc.instantiate(this.trap);
                trap.parent = this.node;
                trap.getComponent(Trap).updateSize(this.is18);
                trap.position = cc.v3(this.offsetMap * brickData.x, this.offsetMap * brickData.y);
                this.listTrap.push({
                    x: brickData.x,
                    y: brickData.y,
                    type: TYPEMAP.TRAP,
                    obj: trap.getComponent(Trap),
                });
                node = trap;
                break;
            case TYPEMAP.APPLE:
                let apple: cc.Node = cc.instantiate(this.apple);
                apple.parent = this.node
                apple.getComponent(cc.Sprite).spriteFrame = this.appleSF;
                apple.width = this.offsetMap;
                apple.height = this.offsetMap;
                apple.position = cc.v3(this.offsetMap * brickData.x, this.offsetMap * brickData.y);
                node = apple;
                this.listApple.push({
                    x: brickData.x,
                    y: brickData.y,
                    type: TYPEMAP.APPLE,
                    obj: apple.getComponent(Apple),
                });
                break;
            case TYPEMAP.SAW:
                let saw: cc.Node = cc.instantiate(this.saw);
                saw.parent = this.node
                saw.width = this.offsetMap;
                saw.height = this.offsetMap;
                saw.position = cc.v3(this.offsetMap * brickData.x, this.offsetMap * brickData.y);
                node = saw;
                this.listSaw.push({
                    x: brickData.x,
                    y: brickData.y,
                    type: TYPEMAP.SAW,
                    obj: saw.getComponent(Saw),
                });
                break;
            case TYPEMAP.END:
                let end: cc.Node = cc.instantiate(this.holeEnd);
                end.parent = this.node
                end.position = cc.v3(this.offsetMap * brickData.x, this.offsetMap * brickData.y);
                this.posHoleEnd = {
                    x: brickData.x,
                    y: brickData.y,
                    type: TYPEMAP.END,
                }
                break;
        }
        return node;
    }

    //Stone

    findStone(posStone){
        for (let index = 0; index < this.listStone.length; index++) {
            if (this.listStone[index].x == posStone.x || this.listStone[index].y == posStone.y) {
                return index;
            }
        }
    }

    updateAndMoveStonePos(indexStone: number, newPos){
        if (indexStone) {
            this.listStone[indexStone] = {...newPos, ...this.listStone[indexStone]}
            this.listStone[indexStone].obj.moveStoneTo({x: newPos.x * this.offsetMap, y: newPos.x * this.offsetMap})
        }
    }

    
}
