/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Cursor
 */
import { RelativePosition, UiEvent } from "@itwin/appui-abstract";
import { Point } from "@itwin/core-react";
/** Enum for Cursor Direction parts
 *  @public
 */
export var CursorDirectionParts;
(function (CursorDirectionParts) {
    CursorDirectionParts[CursorDirectionParts["Top"] = 4096] = "Top";
    CursorDirectionParts[CursorDirectionParts["Left"] = 256] = "Left";
    CursorDirectionParts[CursorDirectionParts["Right"] = 16] = "Right";
    CursorDirectionParts[CursorDirectionParts["Bottom"] = 1] = "Bottom";
})(CursorDirectionParts || (CursorDirectionParts = {}));
/** Enum for Cursor Direction
 * @public
 */
export var CursorDirection;
(function (CursorDirection) {
    CursorDirection[CursorDirection["None"] = 0] = "None";
    CursorDirection[CursorDirection["Top"] = 4096] = "Top";
    CursorDirection[CursorDirection["Left"] = 256] = "Left";
    CursorDirection[CursorDirection["Right"] = 16] = "Right";
    CursorDirection[CursorDirection["Bottom"] = 1] = "Bottom";
    CursorDirection[CursorDirection["TopLeft"] = 4352] = "TopLeft";
    CursorDirection[CursorDirection["TopRight"] = 4112] = "TopRight";
    CursorDirection[CursorDirection["BottomLeft"] = 257] = "BottomLeft";
    CursorDirection[CursorDirection["BottomRight"] = 17] = "BottomRight";
})(CursorDirection || (CursorDirection = {}));
/** Cursor Updated Event class.
 * @public
 */
export class CursorUpdatedEvent extends UiEvent {
}
/** Cursor Information class
 * @public
 */
class CursorInformation {
    /** The cursor position. */
    static get cursorPosition() {
        return this._cursorPosition;
    }
    static set cursorPosition(pt) {
        this._cursorPosition = Point.create(pt);
    }
    /** Gets the cursor X position. */
    static get cursorX() {
        return this._cursorPosition.x;
    }
    /** Gets the cursor Y position. */
    static get cursorY() {
        return this._cursorPosition.y;
    }
    /** Gets the general cursor movement direction. */
    static get cursorDirection() {
        return this._cursorDirection;
    }
    /** Handles the mouse movement.  Sets the cursor position and direction and emits onCursorUpdatedEvent. */
    static handleMouseMove(point) {
        const oldPt = CursorInformation.cursorPosition;
        const direction = this._determineMostFrequentDirection(this._cursorDirections, this._cursorPosition, Point.create(point));
        this.cursorPosition = point;
        this._cursorDirection = direction;
        this.onCursorUpdatedEvent.emit({ oldPt, newPt: point, direction });
    }
    static _determineMostFrequentDirection(cursorDirections, oldPt, newPt) {
        const cursorDirection = this._determineCursorDirection(oldPt, newPt);
        cursorDirections.push(cursorDirection);
        if (cursorDirections.length > 10)
            cursorDirections.shift();
        return this._mostFrequent(cursorDirections);
    }
    static _mostFrequent(array) {
        const hashMap = new Map();
        let maxCount = 0, mostFrequent = CursorDirection.None;
        array.forEach((value) => {
            const key = value;
            let frequency = hashMap.get(key);
            if (frequency !== undefined)
                frequency++;
            else
                frequency = 1;
            hashMap.set(key, frequency);
            if (frequency > maxCount) {
                mostFrequent = key;
                maxCount = frequency;
            }
        });
        return mostFrequent;
    }
    static _determineCursorDirection(oldPt, newPt) {
        let directionParts = 0;
        if (newPt.x < oldPt.x)
            directionParts |= CursorDirectionParts.Left;
        else if (newPt.x > oldPt.x)
            directionParts |= CursorDirectionParts.Right;
        if (newPt.y < oldPt.y)
            directionParts |= CursorDirectionParts.Top;
        else if (newPt.y > oldPt.y)
            directionParts |= CursorDirectionParts.Bottom;
        const direction = directionParts;
        return direction;
    }
    /** Gets the relative position based on the cursor direction. */
    static getRelativePositionFromCursorDirection(cursorDirection) {
        let relativePosition = RelativePosition.BottomRight;
        switch (cursorDirection) {
            case CursorDirection.Top:
                relativePosition = RelativePosition.Top;
                break;
            case CursorDirection.Left:
                relativePosition = RelativePosition.Left;
                break;
            case CursorDirection.Right:
                relativePosition = RelativePosition.Right;
                break;
            case CursorDirection.Bottom:
                relativePosition = RelativePosition.Bottom;
                break;
            case CursorDirection.TopLeft:
                relativePosition = RelativePosition.TopLeft;
                break;
            case CursorDirection.TopRight:
                relativePosition = RelativePosition.TopRight;
                break;
            case CursorDirection.BottomLeft:
                relativePosition = RelativePosition.BottomLeft;
                break;
            case CursorDirection.BottomRight:
                relativePosition = RelativePosition.BottomRight;
                break;
        }
        return relativePosition;
    }
    /** @internal - for testing */
    static clearCursorDirections() {
        this._cursorDirections.length = 0;
    }
}
CursorInformation._cursorPosition = new Point();
CursorInformation._cursorDirection = CursorDirection.BottomRight;
CursorInformation._cursorDirections = new Array();
/** Gets the [[CursorUpdatedEvent]]. */
CursorInformation.onCursorUpdatedEvent = new CursorUpdatedEvent();
export { CursorInformation };
//# sourceMappingURL=CursorInformation.js.map