import GeometryPoint from "./geometry/GeometryPoint.js";
import GeometryRect from "./geometry/GeometryRect.js";

export default class Camera
{
    constructor(x = 0, y = 0, width = window.innerWidth, height = window.innerHeight)
    {
        this.position = new GeometryPoint(x, y);
        this.width = width;
        this.height = height;
        this.borderTop = 0;
        this.borderBottom = undefined;
        this.borderLeft = 0;
        this.borderRight = undefined;
        this.speedX = 0;
        this.speedY = 0;
        this.speedMax = 12;
    }

    centerCamera(x, y)
    {
        this.position.x = x - this.width * 0.5;
        this.position.y = y - this.height * 0.5;

        if (this.position.x < this.borderLeft) {
            this.position.x = this.borderLeft;
        } else if (this.borderRight !== undefined && this.position.x + this.width > this.borderRight) {
            this.position.x = this.borderRight - this.width;
        }

        if (this.position.y < this.borderTop) {
            this.position.y = this.borderTop;
        } else if (this.borderBottom !== undefined && this.position.y + this.height > this.borderBottom) {
            this.position.y = this.borderBottom - this.height;
        }
    }

    centerCameraX(x)
    {
        this.position.x = x - this.width * 0.5;

        if (this.position.x < this.borderLeft) {
            this.position.x = this.borderLeft;
        } else if (this.borderRight !== undefined && this.position.x + this.width > this.borderRight) {
            this.position.x = this.borderRight - this.width;
        }
    }

    lockCameraIntoBorders()
    {
        this.lockCameraIntoHorizontalBorders();
        this.lockCameraIntoVerticalBorders();
    }

    lockCameraIntoHorizontalBorders()
    {
        let hasBeenLocked = false;

        if (this.position.x < this.borderLeft) {
            this.position.x = this.borderLeft;
            hasBeenLocked = true;
        } else if (this.borderRight !== undefined && this.position.x + this.width > this.borderRight) {
            this.position.x = this.borderRight - this.width;
            hasBeenLocked = true;
        }

        return hasBeenLocked;
    }

    lockCameraIntoVerticalBorders()
    {
        let hasBeenLocked = false;

        if (this.position.y < this.borderTop) {
            this.position.y = this.borderTop;
            hasBeenLocked = true;
        } else if (this.borderBottom !== undefined && this.position.y + this.height > this.borderBottom) {
            this.position.y = this.borderBottom - this.height;
            hasBeenLocked = true;
        }

        return hasBeenLocked;
    }

    focusPosition(x, y, reactionLatency = 1)
    {
        this.focusPositionX(x, reactionLatency);
        this.focusPositionY(y, reactionLatency);
    }

    focusPositionX(x, reactionLatency = 1)
    {
        let centerX = this.position.x + this.width * 0.5;
        let distanceX = x - centerX;

        if (!this.lockCameraIntoHorizontalBorders() && distanceX !== 0) {
            if (Math.abs(distanceX) < 1) {
                this.position.x = x - this.width * 0.5;
            } else {
                this.position.x += distanceX * (1 / reactionLatency);
            }
        }
    }

    focusPositionY(y, reactionLatency = 1)
    {
        let centerY = this.position.y + this.height * 0.5;
        let distanceY = y - centerY;

        if (distanceY !== 0) {
            if (Math.abs(distanceY) < 1) {
                this.position.y = y - this.height * 0.5;
            } else {
                this.position.y += distanceY * (1 / reactionLatency);
            }
        }
    }

    getViewAsRect()
    {
        return new GeometryRect(this.position.x, this.position.y, this.width, this.height);
    }

    isMovableInsideView(movable)
    {
        let viewRect = this.getViewAsRect();
        let distanceMovable = movable.getRect().getDiagonal().getLength() * 0.5;
        let distanceCamera = viewRect.getDiagonal().getLength() * 0.5;

        let distanceMin = distanceMovable + distanceCamera;

        return movable.getCenter().getDistanceToPoint(viewRect.getCenter()) < distanceMin;
    }
}