const { ccclass, property } = cc._decorator;

@ccclass
export default class Test extends cc.Component {

    private fan1: cc.Node;
    private v1x: number;
    private v1y: number;
    private v2x: number;
    private v2y: number;
    private circle1: cc.Node;

    private debug: cc.Graphics;

    protected start(): void {
        this.fan1 = this.node.getChildByName("fan1");
        this.circle1 = this.node.getChildByName("circle1");
        this.debug = this.node.getChildByName("debug").getComponent(cc.Graphics);

        this.fan1.width = this.fan1.height = 100 + Math.random() * 200;
        this.circle1.width = this.circle1.height = 50 + Math.random() * 100;
        const fan1 = this.fan1.getComponent(cc.Sprite);
        fan1.fillStart = Math.random();
        fan1.fillRange = 0.5 * Math.random();//书中的结论只对小于180度的扇形正确
        const r1 = this.fan1.width / 2;
        const rad1 = fan1.fillStart * Math.PI * 2;
        this.v1x = r1 * Math.cos(rad1);
        this.v1y = r1 * Math.sin(rad1);
        const rad2 = rad1 + fan1.fillRange * Math.PI * 2;
        this.v2x = r1 * Math.cos(rad2);
        this.v2y = r1 * Math.sin(rad2);

        let oldP: cc.Vec2;
        this.circle1.on(cc.Node.EventType.TOUCH_START, (evt: cc.Event.EventTouch) => {
            oldP = evt.getLocation();
        });
        this.circle1.on(cc.Node.EventType.TOUCH_MOVE, (evt: cc.Event.EventTouch) => {
            const p = evt.getLocation();
            this.circle1.x += p.x - oldP.x;
            this.circle1.y += p.y - oldP.y;
            oldP = p;
            this.checkHit();
        });
    }

    private checkHit(): void {
        this.debug.clear();
        this.debug.circle(this.circle1.x, this.circle1.y, 4);

        if (this.扇形与圆碰撞(this.fan1.x, this.fan1.y, this.fan1.width / 2, this.v1x, this.v1y, this.v2x, this.v2y, this.circle1.x, this.circle1.y, this.circle1.width / 2)) {
            this.fan1.color = cc.Color.RED;
            this.circle1.color = cc.Color.RED;
        } else {
            this.fan1.color = cc.Color.BLUE;
            this.circle1.color = cc.Color.GREEN;
        }
        this.debug.stroke();
    }

    private 扇形与圆碰撞(xf: number, yf: number, rf: number, v1x: number, v1y: number, v2x: number, v2y: number, xc: number, yc: number, rc: number): boolean {
        const dx = xc - xf;
        const dy = yc - yf;
        const rr = rf + rc;
        const dd = dx * dx + dy * dy;
        if (dd < rr * rr) {//圆心与扇心的距离小于（圆的半径+扇形的半径）
            this.debug.circle(xf, yf, rr);

            if (dd < rc * rc) {//扇心在圆内
                this.debug.circle(xf, yf, 2);
                this.debug.circle(xc, yc, rc);
                return true;
            }

            //1 解方程组法
            // const delta = v1x * v2y - v2x * v1y;//对小于180度的扇形，delta总是>0
            // //console.log("delta=" + delta);
            // const a = (v2y * dx - v2x * dy) / delta;
            // const b = (-v1y * dx + v1x * dy) / delta;
            // if (a > 0 && b > 0) {
            //     this.debug.circle(xc, yc, 2);
            //     this.debug.moveTo(xf, yf);
            //     this.debug.lineTo(xf + v1x, yf + v1y);
            //     this.debug.arc(xf, yf, rf, Math.atan2(v1y, v1x), Math.atan2(v2y, v2x), true);
            //     this.debug.lineTo(xf, yf);
            //     return true;
            // }

            //2 外积法
            if (dx * v1y - dy * v1x < 0) {//圆心在扇形起边的左边
                this.debug.moveTo(xf, yf);
                this.debug.lineTo(xf + v1x, yf + v1y);
                if (dx * v2y - dy * v2x > 0) {//圆心在扇形终边的右边
                    this.debug.moveTo(xf, yf);
                    this.debug.lineTo(xf + v2x, yf + v2y);
                    return true;
                }
            }

            let t: number = this.线段与圆相交(dx, dy, v1x, v1y, rc);
            if (t > 0) {
                this.debug.moveTo(xf, yf);
                this.debug.lineTo(xf + v1x, yf + v1y);
                this.debug.circle(xf + t * v1x, yf + t * v1y, 2);
                return true;
            }

            t = this.线段与圆相交(dx, dy, v2x, v2y, rc);
            if (t > 0) {
                this.debug.moveTo(xf, yf);
                this.debug.lineTo(xf + v2x, yf + v2y);
                this.debug.circle(xf + t * v2x, yf + t * v2y, 2);
                return true;
            }

        }
        return false;
    }

    private 线段与圆相交(dx: number, dy: number, vx: number, vy: number, rc: number): number {
        const a = vx * vx + vy * vy;
        const b = -(dx * vx + dy * vy);
        const c = dx * dx + dy * dy - rc * rc;
        const d = b * b - a * c;
        if (d >= 0) {
            const t = (-b - Math.sqrt(d)) / a;
            if (t > 0 && t < 1) {
                return t;
            }
        }
        return 0;
    }

}
