
cc.Class({
    extends: cc.Component,

    properties: {
        water: cc.Prefab,
        waterLayer: cc.Node,
        ground: cc.Node,
        graphics: cc.Graphics,
    },

    // LIFE-CYCLE CALLBACKS:

    onLoad() {
        //
        this.DIG_RADIUS = 50;
        this.DIG_FRAGMENT = 12;
        //
        this.DIG_OPTIMIZE_SIZE = 1;
        //
        cc.macro.ENABLE_MULTI_TOUCH = false;
        let manager = cc.director.getPhysicsManager();
        manager.enabled = true;
        // cc.director.getPhysicsManager().debugDrawFlags = true;
        manager.enabledAccumulator = true;
        cc.PhysicsManager.FIXED_TIME_STEP = 1 / 30;
        manager.VELOCITY_ITERATIONS = 8;
        manager.POSITION_ITERATIONS = 8;
        //
        for (let index = 0; index < 100; index++) {
            c = this.ground.addComponent(cc.PhysicsChainCollider);
            c.loop = true;
            c.enabled = false;
        }
        // this.node.on("touchstart", this.creatWater, this);
    },
    start() {
        //
        this.ground.on(cc.Node.EventType.TOUCH_START, this._touchMove, this);
        this.ground.on(cc.Node.EventType.TOUCH_MOVE, this._touchMove, this);
        //
        this.reset();
        //
        this.schedule(this.creatWater, 0.5);
    },
    _optimizePoint(point) {
        return [Math.floor(point[0] * this.DIG_OPTIMIZE_SIZE) / this.DIG_OPTIMIZE_SIZE, Math.floor(point[1] * this.DIG_OPTIMIZE_SIZE) / this.DIG_OPTIMIZE_SIZE];
    },
    _optimizeRegions() {
        let regions = [];
        for (let index = 0; index < this._regions.length; index++) {
            let pos = this._regions[index];
            let newPos = [];
            pos.forEach((p, i) => {
                p = this._optimizePoint(p);
                let p_pre = this._optimizePoint(pos[(i - 1 + pos.length) % pos.length]);
                let p_next = this._optimizePoint(pos[(i + 1) % pos.length]);
                let vec1 = cc.v2(p[0] - p_pre[0], p[1] - p_pre[1]);
                let vec2 = cc.v2(p_next[0] - p[0], p_next[1] - p[1]);
                if (vec1.lengthSqr() != 0 && vec2.lengthSqr() != 0 && vec1.cross(vec2) != 0) {
                    newPos.push(p);
                }
            })
            if (newPos.length > 2) {
                regions.push(newPos);
            }
        }
        this._regions = regions;
    },
    reset() {
        this._regions = [
            [[-cc.winSize.width / 2, -320], [-cc.winSize.width / 2, 250], [cc.winSize.width / 2, 250], [cc.winSize.width / 2, -320]]
        ];
        this.draw();
    },
    draw() {
        let chains = this.ground.getComponents(cc.PhysicsChainCollider);
        chains.forEach((c) => {
            c.enabled = false;
        })

        let enabled_chains_points = [[]];

        for (let index = 0; index < this._regions.length; index++) {
            let pos = this._regions[index];
            var poly = chains[index];
            if (!poly) {
                poly = this.ground.addComponent(cc.PhysicsChainCollider);
                poly.loop = true;
            }
            poly.points.length = 0;
            poly.points = pos.map((v, i) => {
                let v2 = cc.v2(v[0], v[1])
                return v2;
            });
            poly.enabled = true;
            enabled_chains_points[index] = poly.points;
        }
        //

        this.graphics.clear(true);
        let enabled_chains_points_sort = enabled_chains_points.map((curPoly, curPoly_i) => {
            let count = enabled_chains_points.reduce((pre, nextPoly, nextPoly_i) => {
                if ((curPoly_i != nextPoly_i)) {
                    let length = curPoly.length;
                    for (let i = 0; i < length; ++i) {
                        let p0 = curPoly[i];
                        if (!cc.Intersection.pointInPolygon(p0, nextPoly))
                            return pre;
                    }
                    return pre + 1;
                }
                return pre;
            }, 0);

            return { curPoly, count };
        }).sort((a, b) => {
            return a.count - b.count;
        })
        enabled_chains_points_sort.forEach(({ curPoly, count }) => {
            this.graphics.fillColor = count % 2 === 0 ? cc.Color.ORANGE : cc.Color.BLACK;
            this._drawPoly(this.graphics, curPoly);
            this.graphics.fill();
        })
    },
    _touchMove(touch) {
        // let regions = [[]];
        // let pos = this.ground.convertToNodeSpaceAR(touch.getLocation());
        // let count = this.DIG_FRAGMENT;
        // for (let index = 0; index < count; index++) {
        //     let r = 2 * Math.PI * index / count;
        //     let x = pos.x + this.DIG_RADIUS * Math.cos(r);
        //     let y = pos.y + this.DIG_RADIUS * Math.sin(r);
        //     regions[0].push([x, y]);
        // }

        let regions = [[]];
        let pos = this.graphics.node.convertToNodeSpaceAR(touch.getLocation());
        let delta = touch.getDelta();
        let count = this.DIG_FRAGMENT;
        if (delta.lengthSqr() < 5) {
            for (let index = 0; index < count; index++) {
                let r = 2 * Math.PI * index / count;
                let x = pos.x + this.DIG_RADIUS * Math.cos(r);
                let y = pos.y + this.DIG_RADIUS * Math.sin(r);
                regions[0].push(this._optimizePoint([x, y]));
            }
        } else {
            let startPos = pos.sub(delta);
            for (let index = 0; index < count; index++) {
                let r = 2 * Math.PI * index / count;
                let vec_x = this.DIG_RADIUS * Math.cos(r);
                let vec_y = this.DIG_RADIUS * Math.sin(r);
                let x, y;
                if (delta.dot(cc.v2(vec_x, vec_y)) > 0) {
                    x = pos.x + vec_x;
                    y = pos.y + vec_y;
                } else {
                    x = startPos.x + vec_x;
                    y = startPos.y + vec_y;
                }
                regions[0].push(this._optimizePoint([x, y]));
            }
        }

        // let result = PolyBool.difference({
        //     regions: this._regions,
        //     inverted: false
        // }, {
        //     regions,
        //     inverted: false
        // });

        let seg1 = PolyBool.segments({
            regions: this._regions,
            inverted: false
        });
        let seg2 = PolyBool.segments({
            regions,
            inverted: false
        });
        let comb = PolyBool.combine(seg1, seg2);
        let result = PolyBool.polygon(PolyBool.selectDifference(comb));
        //
        this._regions = result.regions;
        this._optimizeRegions();
        this.draw();
    },
    _drawPoly(ctx, poly) {
        poly.forEach((pos, i) => {
            if (i === 0)
                ctx.moveTo(pos.x, pos.y);
            else
                ctx.lineTo(pos.x, pos.y);
            ctx.close();
        });
    },



    creatWater() {
        let waterNum = 1;
        for (let i = 0; i < waterNum; i++) {
            let waterPre = cc.instantiate(this.water);
            waterPre.x = 0;
            waterPre.y = cc.winSize.height;
            this.waterLayer.addChild(waterPre);
        }
    },


    // update (dt) {},
});
