import {DispHandleI, DispHandleTypeE, PointI} from "./DispBase";
import {
    calculateRotationAfterPointMove,
    movePointFurtherFromPoint,
    rotatePointAboutCenter
} from "./DispUtil";


export function makeRotateHandlePoints(disp, margin: number,
                                   center: PointI, rotation: number): DispHandleI[] {
    const bounds = disp.bounds;
    if (bounds == null) {
        console.log("No bounds, exiting");
        return [];
    }

    if (disp.tempRotation == null)
        disp.tempRotation = rotation;

    const cp = center;
    const maxRadius = Math.max.apply(Math, [
        Math.hypot(bounds.x + bounds.w - cp.x, cp.y - bounds.y),
        Math.hypot(cp.x - bounds.x, bounds.y + bounds.h - cp.y),
        Math.hypot(bounds.x + bounds.w - cp.x, cp.y - bounds.y),
        Math.hypot(cp.x - bounds.x, bounds.y + bounds.h - cp.y),
        margin
    ]);


    return [
        {
            disp: disp,
            center: {x: cp.x, y: cp.y + maxRadius},
            handleType: DispHandleTypeE.freeRotate
        },
        {
            disp: disp,
            center: {x: cp.x, y: cp.y - maxRadius},
            handleType: DispHandleTypeE.snapRotate
        }
    ]
        .map((handle: DispHandleI) => {
            if (disp.tempRotation != 0)
                handle.center = rotatePointAboutCenter(cp, handle.center, disp.tempRotation);

            handle.center = movePointFurtherFromPoint(cp, handle.center, margin);
            return handle;
        });
}


/** Calculate Rotation from Handle Delta
 *
 * Calculate the rotation and work out the new delta.
 *
 * @param handle
 * @param dx
 * @param dy
 */
export function calculateRotationFromHandleDelta(
    handle: DispHandleI, dx: number, dy: number,
    currentRotation: number,
    tempRotation: number,
    center: PointI): { newRotation: number, deltaRotation: number ,tempRotation:number} {

    if (handle.handleType != DispHandleTypeE.freeRotate
        && handle.handleType != DispHandleTypeE.snapRotate) {
        console.log("ERROR: DispGroup only has rotate handles, "
            + `${handle.handleIndex} passed`);
        return null;
    }

    // Set the center if required
    if (handle.lastDeltaPoint == null) {
        const startPoint: PointI = handle.center;
        handle.lastDeltaPoint = {
            x: startPoint.x,
            y: startPoint.y
        };
    }

    const nextPoint = {
        x: handle.lastDeltaPoint.x + dx,
        y: handle.lastDeltaPoint.y + dy
    };

    let rotationDegreesDelta = calculateRotationAfterPointMove(
        center, handle.lastDeltaPoint, nextPoint
    );

    handle.lastDeltaPoint = nextPoint;

    // Calculate the center rotation
    let newRotation = (tempRotation + rotationDegreesDelta) % 360;
    tempRotation = newRotation;

    // Snap the new rotation for the symbol
    if (handle.handleType == DispHandleTypeE.snapRotate) {
        // Work out the snapped rotation
        newRotation += newRotation < 0 ? -20 : 20; // Add an offset to help snapping
        newRotation = newRotation - (newRotation % 45);
    }

    // Work out how far we need to rotate the disps
    rotationDegreesDelta = newRotation - currentRotation;


    return {
        newRotation: newRotation,
        deltaRotation: rotationDegreesDelta,
        tempRotation: tempRotation
    };
}
