"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ViewHandler = void 0;
const ipc_1 = require("../ipc");
const ViewManager_1 = require("./ViewManager");
const MouseTracker_1 = require("./MouseTracker");
let ViewHandler = class ViewHandler extends ipc_1.EdenEmitter {
    viewManager;
    mouseTracker;
    // Global drag/resize tracking
    dragState = null;
    resizeState = null;
    // We need a way to get running app instances to map appId to viewId
    // Or we can ask ViewManager to find views by appId.
    // ViewManager has getViewsByAppId(appId).
    constructor(viewManager, ipcBridge) {
        super(ipcBridge);
        this.viewManager = viewManager;
        this.mouseTracker = new MouseTracker_1.MouseTracker(8); // ~120fps
    }
    /**
     * Update the bounds (position and size) of a specific view.
     */
    async handleUpdateViewBounds(args) {
        const { appId, bounds } = args;
        const viewIds = this.viewManager.getViewsByAppId(appId);
        if (viewIds.length > 0) {
            // Use the first view (typically there's only one per appId)
            this.viewManager.setViewBounds(viewIds[0], bounds);
            return { success: true };
        }
        throw new Error(`App or view ${appId} is not running`);
    }
    /**
     * Show or hide a specific view.
     */
    async handleSetViewVisibility(args) {
        const { appId, visible } = args;
        const viewIds = this.viewManager.getViewsByAppId(appId);
        if (viewIds.length === 0) {
            throw new Error(`App ${appId} is not running`);
        }
        if (visible) {
            this.viewManager.showView(viewIds[0]);
        }
        else {
            this.viewManager.hideView(viewIds[0]);
        }
        return { success: true };
    }
    /**
     * Bring an application's view to the front and focus it.
     */
    async handleFocusApp(args) {
        const { appId } = args;
        const viewIds = this.viewManager.getViewsByAppId(appId);
        if (viewIds.length === 0) {
            throw new Error(`App ${appId} is not running`);
        }
        this.viewManager.showView(viewIds[0]);
        return { success: true };
    }
    /**
     * Update the available workspace bounds (e.g. after taskbar resize).
     */
    async handleUpdateWorkspaceBounds(args) {
        const { bounds, windowSize } = args;
        this.viewManager.setWorkspaceBounds(bounds);
        this.viewManager.setWindowSize(windowSize);
        this.notify("global-bounds-changed", {
            workspaceBounds: bounds,
            windowSize,
        });
        return { success: true };
    }
    /**
     * Toggle between floating and tiled window modes.
     */
    async handleToggleViewMode(args) {
        const { appId, mode } = args;
        const viewIds = this.viewManager.getViewsByAppId(appId);
        if (viewIds.length === 0) {
            throw new Error(`App ${appId} is not running`);
        }
        this.viewManager.setViewMode(viewIds[0], mode);
        return { success: true };
    }
    /**
     * Start dragging a window.
     */
    async handleStartDrag(args) {
        const { appId, startX, startY } = args;
        const viewIds = this.viewManager.getViewsByAppId(appId);
        if (viewIds.length === 0) {
            throw new Error(`App ${appId} is not running`);
        }
        const viewId = viewIds[0];
        // Get current view bounds
        const viewInfo = this.viewManager.getViewInfo(viewId);
        if (!viewInfo) {
            throw new Error(`View ${viewId} not found`);
        }
        // Stop any existing drag
        if (this.dragState) {
            this.mouseTracker.unsubscribe(`drag-${this.dragState.appId}`);
        }
        // Start tracking global mouse position
        this.dragState = {
            appId,
            startX,
            startY,
            startBounds: { ...viewInfo.bounds },
        };
        // Subscribe to mouse updates
        this.mouseTracker.subscribe(`drag-${appId}`, (position) => {
            if (!this.dragState)
                return;
            const deltaX = position.x - this.dragState.startX;
            const deltaY = position.y - this.dragState.startY;
            const newBounds = {
                x: this.dragState.startBounds.x + deltaX,
                y: this.dragState.startBounds.y + deltaY,
                width: this.dragState.startBounds.width,
                height: this.dragState.startBounds.height,
            };
            this.viewManager.setViewBounds(viewId, newBounds);
            this.notifySubscriber(viewId, "bounds-updated", newBounds);
        });
        return { success: true };
    }
    /**
     * End the current drag operation.
     */
    async handleEndDrag(args) {
        if (this.dragState) {
            this.mouseTracker.unsubscribe(`drag-${this.dragState.appId}`);
            this.dragState = null;
        }
        return { success: true };
    }
    /**
     * Handle global mouse up event to stop any active drag/resize operations.
     */
    async handleGlobalMouseUp() {
        // Cleanup any active drag or resize operations when mouse is released
        if (this.dragState) {
            console.log("[ViewHandler] Global mouseup - cleaning up drag state");
            this.mouseTracker.unsubscribe(`drag-${this.dragState.appId}`);
            this.dragState = null;
        }
        if (this.resizeState) {
            console.log("[ViewHandler] Global mouseup - cleaning up resize state");
            this.mouseTracker.unsubscribe(`resize-${this.resizeState.appId}`);
            this.resizeState = null;
        }
        return { success: true };
    }
    /**
     * Start resizing a window.
     */
    async handleStartResize(args) {
        const { appId, startX, startY } = args;
        const viewIds = this.viewManager.getViewsByAppId(appId);
        if (viewIds.length === 0) {
            throw new Error(`App ${appId} is not running`);
        }
        const viewId = viewIds[0];
        // Get current view bounds
        const viewInfo = this.viewManager.getViewInfo(viewId);
        if (!viewInfo) {
            throw new Error(`View ${viewId} not found`);
        }
        // Stop any existing resize
        if (this.resizeState) {
            this.mouseTracker.unsubscribe(`resize-${this.resizeState.appId}`);
        }
        // Initialize resize state
        this.resizeState = {
            appId,
            startX,
            startY,
            startBounds: { ...viewInfo.bounds },
            currentWidth: viewInfo.bounds.width,
            currentHeight: viewInfo.bounds.height,
        };
        // Subscribe to mouse updates
        this.mouseTracker.subscribe(`resize-${appId}`, (position) => {
            if (!this.resizeState)
                return;
            const deltaX = position.x - this.resizeState.startX;
            const deltaY = position.y - this.resizeState.startY;
            let targetWidth = this.resizeState.startBounds.width + deltaX;
            let targetHeight = this.resizeState.startBounds.height + deltaY;
            // Apply minimum size
            targetWidth = Math.max(targetWidth, 200);
            targetHeight = Math.max(targetHeight, 200);
            this.resizeState.currentWidth = targetWidth;
            this.resizeState.currentHeight = targetHeight;
            const newBounds = {
                x: this.resizeState.startBounds.x,
                y: this.resizeState.startBounds.y,
                width: Math.round(this.resizeState.currentWidth),
                height: Math.round(this.resizeState.currentHeight),
            };
            this.viewManager.setViewBounds(viewId, newBounds);
            this.notifySubscriber(viewId, "bounds-updated", newBounds);
        });
        return { success: true };
    }
    /**
     * End the current resize operation.
     */
    async handleEndResize(args) {
        if (this.resizeState) {
            this.mouseTracker.unsubscribe(`resize-${this.resizeState.appId}`);
            this.resizeState = null;
        }
        return { success: true };
    }
    /**
     * Get the current dimensions of the main window.
     */
    async handleGetWindowSize() {
        return this.viewManager.getWindowSize();
    }
};
exports.ViewHandler = ViewHandler;
__decorate([
    (0, ipc_1.EdenHandler)("update-view-bounds"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleUpdateViewBounds", null);
__decorate([
    (0, ipc_1.EdenHandler)("set-view-visibility"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleSetViewVisibility", null);
__decorate([
    (0, ipc_1.EdenHandler)("focus-app"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleFocusApp", null);
__decorate([
    (0, ipc_1.EdenHandler)("update-global-bounds"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleUpdateWorkspaceBounds", null);
__decorate([
    (0, ipc_1.EdenHandler)("toggle-view-mode"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleToggleViewMode", null);
__decorate([
    (0, ipc_1.EdenHandler)("start-drag"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleStartDrag", null);
__decorate([
    (0, ipc_1.EdenHandler)("end-drag"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleEndDrag", null);
__decorate([
    (0, ipc_1.EdenHandler)("global-mouseup"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleGlobalMouseUp", null);
__decorate([
    (0, ipc_1.EdenHandler)("start-resize"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleStartResize", null);
__decorate([
    (0, ipc_1.EdenHandler)("end-resize"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleEndResize", null);
__decorate([
    (0, ipc_1.EdenHandler)("window-size"),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], ViewHandler.prototype, "handleGetWindowSize", null);
exports.ViewHandler = ViewHandler = __decorate([
    (0, ipc_1.EdenNamespace)("view"),
    __metadata("design:paramtypes", [ViewManager_1.ViewManager, ipc_1.IPCBridge])
], ViewHandler);
//# sourceMappingURL=ViewHandler.js.map