const { ccclass, property } = cc._decorator;

@ccclass
export default class Test extends cc.Component {

    private rect1: cc.Node;
    private circle1: cc.Node;
    private circle2: cc.Node;
    private circle3: cc.Node;

    private debug: cc.Graphics;

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

        let oldP: cc.Vec2;
        const touch_start = (evt: cc.Event.EventTouch) => {
            oldP = evt.getLocation();
        };
        const touch_move = (evt: cc.Event.EventTouch) => {
            const p = evt.getLocation();
            evt.target.x += p.x - oldP.x;
            evt.target.y += p.y - oldP.y;
            oldP = p;
            const dx = this.circle2.x - this.circle1.x;
            const dy = this.circle2.y - this.circle1.y;
            this.rect1.x = this.circle1.x;
            this.rect1.y = this.circle1.y;
            this.rect1.width = Math.sqrt(dx * dx + dy * dy);
            this.rect1.angle = Math.atan2(dy, dx) * 180 / Math.PI;
            this.circle2.x = this.rect1.x + dx;
            this.circle2.y = this.rect1.y + dy;
            this.checkHit();
        };

        this.rect1.on(cc.Node.EventType.TOUCH_START, touch_start);
        this.rect1.on(cc.Node.EventType.TOUCH_MOVE, (evt: cc.Event.EventTouch) => {
            const p = evt.getLocation();
            this.circle1.x = this.rect1.x += p.x - oldP.x;
            this.circle1.y = this.rect1.y += p.y - oldP.y;
            oldP = p;
            const rad = this.rect1.angle * Math.PI / 180;
            this.circle2.x = this.rect1.x + Math.cos(rad) * this.rect1.width;
            this.circle2.y = this.rect1.y + Math.sin(rad) * this.rect1.width;
            this.checkHit();
        });
        this.circle1.on(cc.Node.EventType.TOUCH_START, touch_start);
        this.circle1.on(cc.Node.EventType.TOUCH_MOVE, touch_move);
        this.circle2.on(cc.Node.EventType.TOUCH_START, touch_start);
        this.circle2.on(cc.Node.EventType.TOUCH_MOVE, touch_move);
        this.circle3.on(cc.Node.EventType.TOUCH_START, touch_start);
        this.circle3.on(cc.Node.EventType.TOUCH_MOVE, touch_move);
    }

    private checkHit(): void {
        this.debug.clear();
        this.debug.circle(this.circle3.x, this.circle3.y, 4);
        const r1 = this.circle1.width / 2;
        const r2 = this.circle3.width / 2;
        if (this.点q到线段ab距离的平方(this.circle2.x - this.circle1.x, this.circle2.y - this.circle1.y, this.circle1.x, this.circle1.y, this.circle3.x, this.circle3.y) < (r1 + r2) * (r1 + r2)) {
            this.rect1.color = cc.Color.RED;
            this.circle1.color = cc.Color.RED;
            this.circle2.color = cc.Color.RED;
            this.circle3.color = cc.Color.RED;
        } else {
            this.rect1.color = cc.Color.BLUE;
            this.circle1.color = cc.Color.BLUE;
            this.circle2.color = cc.Color.BLUE;
            this.circle3.color = cc.Color.GREEN;
        }
        this.debug.stroke();
    }

    private 点q到线段ab距离的平方(ax: number, ay: number, bx: number, by: number, qx: number, qy: number): number {
        this.debug.circle(bx, by, 2);
        this.debug.moveTo(bx, by);
        this.debug.lineTo(bx + ax, by + ay);
        let t: number = (ax * (qx - bx) + ay * (qy - by)) / (ax * ax + ay * ay);
        if (t < 0) t = 0;
        else if (t > 1) t = 1;
        const px = ax * t + bx;
        const py = ay * t + by;
        this.debug.circle(px, py, 2);
        this.debug.moveTo(px, py);
        this.debug.lineTo(qx, qy);
        const dx = qx - px;
        const dy = qy - py;
        return dx * dx + dy * dy;
    }

}
