import ccclass = cc._decorator.ccclass;
import property = cc._decorator.property;
import requireComponent = cc._decorator.requireComponent;
import menu = cc._decorator.menu;
import Component = cc.Component;
import Enum = cc.Enum;
import Size = cc.Size;
import Vec2 = cc.Vec2;
import Graphics = cc.Graphics;
import Node = cc.Node;
import macro = cc.macro;
import Color = cc.Color;
import { LQCollideShape, LQCollideStatus } from "../lq_base/data/lq_const";
import { LQCollideConfig, LQCollideInfoList } from "./lq_collide_config";
import { LQCollideSystem } from "./lq_collide_system";
import { LQRect } from "../lq_base/data/lq_data";
import { LQCollideBase } from "./lq_collide_base";
import { LQGameUtil } from "../lq_base/util/lq_game_util";
import MapConroler from "../Map";

@ccclass
@requireComponent(LQCollideBase)
@menu("lq/collide")
export class LQCollide extends Component {
    velocity: any;
    @property({ displayName: '绘制形状' })
    get draw_collide(): boolean {
        return this._draw_collide;
    }

    set draw_collide(value: boolean) {
        this._draw_collide = value;
        this.draw_shape();
    }

    @property
    protected _draw_collide: boolean = true;

    @property({ tooltip: '能否移动' })
    protected can_move: boolean = true;


    @property({
        tooltip: '碰撞形状，None就是无敌，不参与碰撞',
        type: Enum(LQCollideShape),
        displayName: '碰撞形状'
    })
    get collide_shape(): LQCollideShape {
        return this._collide_shape;
    }

    set collide_shape(value: LQCollideShape) {
        this._collide_shape = value;
        this.draw_shape();
    }

    @property()
    public _collide_shape: LQCollideShape = LQCollideShape.Rect;

    @property({
        type: Enum(LQCollideInfoList), tooltip: '碰撞类别',
        displayName: '碰撞类别'
    })
    get collide_group_index() {
        if (this._collide_group_index === -1) {
            this._collide_group_index = LQCollideSystem.get_info_by_id(this.collide_group_id).index;
        }
        return this._collide_group_index;
    }

    set collide_group_index(value) {
        if (this._collide_group_index === value) {
            return;
        }
        this._collide_group_index = value;
        this.collide_group_id = LQCollideSystem.get_group_by_index(value).id;
    }

    @property({ serializable: false })
    private _collide_group_index = -1;

    @property({ visible: false })
    protected collide_group_id: number = 0;

    @property({ visible: false })
    protected collide_scle: number = 1;

    @property({
        tooltip: 'collide半径',
        visible() {
            // @ts-ignore
            return this._collide_shape === LQCollideShape.Circle;
        },
        displayName: '半径'
    })
    get radius(): number {
        return this._radius;
    }

    set radius(value: number) {
        this._radius = value;
        this.draw_shape();
    }

    @property()
    protected _radius: number = 50;

    // 物体速度
    // public velocity: Vec2 = new Vec2(0, 0);

    @property({
        tooltip: 'collide长宽',
        visible() {
            // @ts-ignore
            return this._collide_shape === LQCollideShape.Rect;
        },
        displayName: '长宽'
    })
    get size(): Size {
        return this._size;
    }

    set size(value: Size) {
        this._size = value;
        if (this.world_rect) {
            this.world_rect.width = value.width;
            this.world_rect.height = value.height;
            this.world_rect.half_width = value.width * 0.5;
            this.world_rect.half_height = value.height * 0.5;
        }
        this.draw_shape();
    }

    @property()
    protected _size: Size = new Size(100, 100);

    @property({ displayName: '位置偏移' })
    get offset(): Vec2 {
        return this._offset;
    }

    set offset(value: Vec2) {
        this._offset = value;
        this.draw_shape();
    }

    @property({
        type: Vec2,
        visible() {
            // @ts-ignore
            return this._collide_shape === LQCollideShape.Polygon;
        },
        displayName: '多边形碰撞点'
    })
    get polygon_points(): Vec2[] {
        return this._polygon_points;
    }

    set polygon_points(value: Vec2[]) {
        this._polygon_points = value;
        this.draw_shape();
    }

    @property()
    public _polygon_points: Vec2[] = [new Vec2(-45, -45), new Vec2(45, -45), new Vec2(60, 40), new Vec2(0, 70), new Vec2(-60, 40)];
    //collide碰撞位置偏移
    @property()
    public _offset: Vec2 = new Vec2(0, 0);

    @property({ displayName: '自定义字符串' })
    public data_string: string = '';
    //每个collide的id唯一
    public collide_id: number = 0;
    //状态
    public collide_status: LQCollideStatus = LQCollideStatus.Idle;
    //是否可碰撞
    public is_enable: boolean = true;
    //是否开启碰撞前后的函数
    public is_open_func: boolean = true;
    //碰撞类别
    public collide_category = 0;
    //碰撞筛选
    public collide_mask = 0;
    //缓存多边形碰撞数据
    public cache_polygon_points: number[];
    //绘制collide形状组件
    private _debugDrawer!: Graphics;
    public world_rect!: LQRect;
    public collide_map: { [key: number]: { collide: LQCollide, status: 1 | 2 } } = {};
    public follow_target_category: number | undefined;
    private static id_maker: number = 1;
    public is_music: boolean = false;

    //检测绘制组件是否添加
    private checkDebugDrawValid() {
        if (!this._debugDrawer || !this._debugDrawer.isValid) {
            let node = this.node.getChildByName('Collide');
            if (!node && this.node) {
                node = new Node('Collide');
                node.zIndex = macro.MAX_ZINDEX;
                this.node.addChild(node);
                // @ts-ignore
                node._objFlags = 1096;
                this._debugDrawer = node.addComponent(Graphics);
                this._debugDrawer.lineWidth = 3;
                this._debugDrawer.strokeColor = new Color(255, 0, 0);
                this._debugDrawer.fillColor = new Color(255, 0, 0);
            } else {
                this._debugDrawer = node.getComponent(Graphics);
            }
        }
    }

    //绘制形状
    protected draw_shape() {
        if (!this._draw_collide) {
            if (this._debugDrawer) {
                this._debugDrawer.clear();
            }
            return;
        }
        this.checkDebugDrawValid();
        this._debugDrawer.clear();

        let o1 = { key: 'scaleX', value: this.node.scale };
        let o2 = { key: 'scaleY', value: this.node.scale };
        LQGameUtil.recursion_node_property(this.node, o1);
        LQGameUtil.recursion_node_property(this.node, o2);
        if (o1.value === 0 || o2.value === 0) {
            return;
        }
        this._debugDrawer.node.scaleX = 1 / o1.value;
        this._debugDrawer.node.scaleY = 1 / o2.value;
        switch (this._collide_shape) {
            case LQCollideShape.Circle:
                this._debugDrawer.circle(+this._offset.x, +this._offset.y, this._radius);
                this._debugDrawer.stroke();
                break;
            case LQCollideShape.Rect:
                this._debugDrawer.moveTo(-this._size.width * 0.5 + this._offset.x, -this._size.height * 0.5 + this._offset.y);
                this._debugDrawer.lineTo(-this._size.width * 0.5 + this._offset.x, +this._size.height * 0.5 + this._offset.y);
                this._debugDrawer.lineTo(this._size.width * 0.5 + this._offset.x, +this._size.height * 0.5 + this._offset.y);
                this._debugDrawer.lineTo(this._size.width * 0.5 + this._offset.x, -this._size.height * 0.5 + this._offset.y);
                this._debugDrawer.lineTo(-this._size.width * 0.5 + this._offset.x, -this._size.height * 0.5 + this._offset.y);
                this._debugDrawer.stroke();
                break;
            case LQCollideShape.Polygon:
                this._debugDrawer.moveTo(this._polygon_points[0].x + this._offset.x, this._polygon_points[0].y + this._offset.y);
                for (let i = 1; i < this._polygon_points.length; i++) {
                    this._debugDrawer.lineTo(this._polygon_points[i].x + this._offset.x, this._polygon_points[i].y + this._offset.y);
                }
                this._debugDrawer.lineTo(this._polygon_points[0].x + this._offset.x, this._polygon_points[0].y + this._offset.y);
                this._debugDrawer.stroke();
                break;
        }
    }

    //仅用于矩形
    public update_size(width: number, height: number) {
        this._size.width = width;
        this.world_rect.width = width;
        this.world_rect.half_width = width * 0.5;
        this._size.height = height;
        this.world_rect.height = height;
        this.world_rect.half_height = height * 0.5;

        this.draw_shape();
    }

    public init_lq_collide() {

        this.world_rect = new LQRect(0, 0, this._size.width, this._size.height);
        this.draw_shape();
        const info = LQCollideSystem.get_info_by_id(this.collide_group_id);
        this.collide_mask = info.mask;
        this.collide_category = info.category;
        this.collide_id = LQCollide.id_maker++;

        this.updateCollisionArea();
    }

    private updateCollisionArea() {
        if (this._size.width == 0 || this._size.height == 0 || MapConroler._instance == undefined) {
            return;
        }
        if (MapConroler._instance.node.scale) {
            let scaleX = MapConroler._instance.node.scale;
            let scaleY = MapConroler._instance.node.scale;

            if (scaleX === 0 || scaleX == undefined || scaleX == null || scaleX == 1) {
                return;
            }
            switch (this._collide_shape) {
                case LQCollideShape.Circle:
                    // 圆形碰撞区域半径更新
                    this._radius = this._radius * Math.max(scaleX, scaleY);
                    break;
                case LQCollideShape.Rect:
                    // 矩形碰撞区域尺寸更新
                    // console.log(this.data_string);
                    if (this._size.width !== 10 && this.data_string != "-1" && this.data_string != "-2") {
                        // if(this._size.width == 105 || this._size.height == 105){}
                        this._size.width = this._size.width * scaleX;
                        //  console.log("放大倍数",scaleX);
                    }
                    if (this._size.height !== 10 && this.data_string != "-1" && this.data_string != "-2") {
                        // if(this._size.width == 105 || this._size.height == 105){}
                        this._size.height = this._size.height * scaleY;
                        // console.log("放大倍数",scaleY);
                    }
                    // this._size.width = this._size.width * scaleX;
                    // this._size.height = this._size.height * scaleY;
                    if (this.world_rect) {
                        this.world_rect.width = this._size.width;
                        this.world_rect.height = this._size.height;
                        this.world_rect.half_width = this._size.width * 0.5;
                        this.world_rect.half_height = this._size.height * 0.5;
                    }
                    break;
                case LQCollideShape.Polygon:
                    // 多边形碰撞点坐标更新
                    this._polygon_points = this._polygon_points.map(point => {
                        return new Vec2(point.x * scaleX, point.y * scaleY);
                    });
                    break;
            }

            this.draw_shape();
        }

    }

    public enable_lq_collide() {

        if (this.collide_status === LQCollideStatus.Live) {
            console.warn(this.node.name + '重复添加');
            return;
        }
        this.is_enable = true;
        this.collide_status = LQCollideStatus.Live;
        LQCollideSystem.add_collide(this);
    }

    public disable_lq_collide() {
        if (this.collide_status !== LQCollideStatus.Live) {
            return;
        }
        this.is_enable = false;
        this.collide_status = LQCollideStatus.Idle;
        LQCollideSystem.remove_collide(this);
    }

    public update_lq_collide() {

    }

    //@ts-ignore
    public on_enter(collide: LQCollide) {
        if (this.disableCollider(collide)) {
            return;
        }
        // if (LQCollideConfig.switch_print_log) {
        //     console.log(this.node.name + ' on_enter');
        // }
        let block = this.node.parent.getComponent("Block");

        if (collide.node.name == "rise" && block.type == 9) {
            let otherColor = collide.node.parent.getChildByName("risefall").getChildByName("color").getComponent(cc.Label).string;
            if (block.color == otherColor && this.data_string != "-1" && this.data_string != "-2") {
                return;
            }
            if (block) {
                if (block.block_Info) {
                    if (block.block_Info.node.getComponent("Block").color == otherColor && this.data_string != "-1" && this.data_string != "-2") {
                        return;
                    }
                }
            }

            // if (this.is_music == false) {
            //     this.is_music = true;
            cc.fx.AudioManager._instance.playEffect("simpleColor", null);
            // }

        }
        else if (collide.node.name == "rise" && block.type != 9) {
            let otherColor = collide.node.parent.getChildByName("risefall").getChildByName("color").getComponent(cc.Label).string;
            if (block.color == otherColor) {
                return;
            }
            // if (this.is_music == false) {
            //     this.is_music = true;
            cc.fx.AudioManager._instance.playEffect("simpleColor", null);
            // }
        }
    }

    //@ts-ignore
    public on_exit(collide: LQCollide) {
        if (this.disableCollider(collide)) {
            return;
        }
        if (LQCollideConfig.switch_print_log) {
            if (this.node.parent.getComponent("Block")) {
                let block = this.node.parent.getComponent("Block");
                // if(!block.isTouch){
                //     return;
                // }
                block.checkCollision = false;
                if (this.node.name == "top") {
                    block.moveUp = true;
                }
                if (this.node.name === "down") {
                    block.moveDown = true;
                }
                if (this.node.name === "left") {
                    block.moveLeft = true;
                }
                if (this.node.name === "right") {
                    block.moveRight = true;
                }
                // if (collide.node.name == "rise") {
                //     this.is_music = false;
                // }
            }
        }
    }

    public on_collide(collide: LQCollide): void {
        if (this.disableCollider(collide)) {
            return;
        }
        if (LQCollideConfig.switch_print_log) {
            if (this.node.parent.getComponent("Block")) {
                let block = this.node.parent.getComponent("Block");
                let jg = false;
                if (block.isTouch) {
                    if (collide.node.name == "rise" && block.type == 9) {
                        let otherColor = collide.node.parent.getChildByName("risefall").getChildByName("color").getComponent(cc.Label).string;
                        // console.log("我的顔色", block.color, "粘合顔色", block.block_Info.node.getComponent("Block").color, "單色通過地块颜色：", otherColor, this.data_string);

                        if (block.color == otherColor && this.data_string != "-1" && this.data_string != "-2") {
                            return;
                        }
                        if (block.block_Info.node.getComponent("Block").color == otherColor && (this.data_string == "-1" || this.data_string == "-2")) {
                            return;
                        }
                    }
                    else if (collide.node.name == "rise" && block.type != 9) {
                        let otherColor = collide.node.parent.getChildByName("risefall").getChildByName("color").getComponent(cc.Label).string;
                        if (block.color == otherColor) {
                            return;
                        }
                    }
                    block.checkCollision = true;
                    // console.log("碰撞",this.node.name);

                    if (this.node.name == "top") {
                        // console.log(collide.node.parent.name);
                        block.moveUp = false;
                        if (block.touchPointY > (this.node.parent.y + this.node.parent.height)) {
                            block.moveY = 1;
                        }
                        // console.log("碰到上边缘");
                    }
                    if (this.node.name === "down") {

                        block.moveDown = false;
                        if (block.touchPointY < (this.node.parent.y)) {
                            block.moveY = -1;
                        }
                        // console.log("碰到下边缘");
                    }
                    if (this.node.name === "left") {
                        block.moveLeft = false;
                        if (block.touchPointX < (this.node.parent.x - this.node.parent.width)) {
                            block.moveX = -1;
                        }
                    }
                    if (this.node.name === "right") {
                        block.moveRight = false;
                        if (block.touchPointX > (this.node.parent.x)) {
                            block.moveX = 1;
                        }
                    }

                    if (this.node.name.startsWith("tan") && collide.node.name.startsWith("tan")) {
                        // console.log("_____________" + this.node.name);
                        if (this.node.name == "tan_down_left" && collide.node.name == "tan_up_right") {
                            block.Bounce(this.node.name);
                        }
                        else if (this.node.name == "tan_down_right" && collide.node.name == "tan_up_left") {
                            block.Bounce(this.node.name);
                        }
                        else if (this.node.name == "tan_up_left" && collide.node.name == "tan_down_right") {
                            block.Bounce(this.node.name);
                        }
                        else if (this.node.name == "tan_up_right" && collide.node.name == "tan_down_left") {
                            block.Bounce(this.node.name);
                        }
                    }
                }
            }
        }
    }

    public disableCollider(collide: LQCollide) {
        let jg = false;
        if (collide.node && this.node) {
            if (collide.node.parent && this.node.parent) {
                if (collide.node.parent.uuid == this.node.parent.uuid) {
                    jg = true;
                }
                if (this.node.parent.getComponent("Block")) {
                    let block = this.node.parent.getComponent("Block");
                    if (block.type == 1 || block.type == 10 || block.type == 9) {
                        if (collide.node.parent == block.block_Info.node) {
                            jg = true;
                        }
                    }
                }
            }
        }


        return jg;
    }
}