/*-
 * ~~~~~~licensing~~~~~~
 * entaxy-management-plugin
 * ==========
 * Copyright (C) 2020 - 2025 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
var Entaxy;
(function(Entaxy) {
    'use strict';

    Entaxy._module.factory('ContextMenuService', function() {
        return {
            element: null,
            menuElement: null
        };
    }).directive('contextMenu', ['$document', 'ContextMenuService', function($document, ContextMenuService) {
        return {
            restrict: 'A',
            scope: {
                'item': '=',
                'callback': '&contextMenu',
                'contextMenuOptions': '='
            },
            link: function($scope, $element, $attrs) {

                function createMenuElement() {
                    let contextMenuOptions = $scope.contextMenuOptions;
                    if (contextMenuOptions && contextMenuOptions.length > 0) {
                        let menuElementContainer = document.createElement("div");
                        menuElementContainer.id = "context-menu";
                        menuElementContainer.className = "dropdown";
                        menuElementContainer.style.position = "fixed";
                        let menuElement = menuElementContainer.appendChild(document.createElement("ul"));
                        menuElement.className = "dropdown-menu";
                        contextMenuOptions.forEach(option => {
                            let optionElement = menuElement.appendChild(document.createElement("li"));
                            if (option.divider) {
                                optionElement.className = 'divider';
                            } else {
                                let optionRefElement = optionElement.appendChild(document.createElement("a"));
                                optionRefElement.appendChild(document.createTextNode(option.name));
                                optionRefElement.onclick = (event) => handleAction(event, option.actionFn);
                            }
                        });
                        return menuElementContainer;
                    }
                }

                function handleAction(event, actionFn) {
                    event.preventDefault();
                    event.stopPropagation();
                    if (event.button === 0) {
                        if (actionFn) {
                            actionFn($scope.item);
                        }
                    }
                    handleClickEvent(event);
                }

                let opened = false;

                function open(event, menuElement) {
                    menuElement.addClass('open');

                    let viewportHeight =
                        Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
                    let viewportWidth =
                        Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
                    let elementHeight = menuElement[0].scrollHeight;
                    let elementWidth = menuElement[0].scrollWidth;
                    let top = event.clientY;
                    let left = event.clientX;

                    if (top > (viewportHeight - elementHeight)) {
                        top -= elementHeight;
                    }
                    if (left > (viewportWidth - elementWidth)) {
                        left -= elementWidth;
                    }

                    menuElement.css('top', top + 'px');
                    menuElement.css('left', left + 'px');
                    opened = true;
                }

                function close(menuElement) {
                    menuElement.removeClass('open');
                    menuElement.remove();
                    opened = false;
                }

                $element.bind('contextmenu', function(event) {
                    if (ContextMenuService.menuElement !== null) {
                        close(ContextMenuService.menuElement);
                    }
                    $element[0].appendChild(createMenuElement());
                    ContextMenuService.menuElement = angular.element(
                        document.getElementById("context-menu")
                    );
                    ContextMenuService.element = event.target;

                    event.preventDefault();
                    event.stopPropagation();

                    $scope.$apply(function() {
                        $scope.callback({ $event: event });
                    });

                    $scope.$apply(function() {
                        open(event, ContextMenuService.menuElement);
                    });
                });

                function handleKeyUpEvent(event) {
                    if (opened && event.keyCode === 27) {
                        $scope.$apply(function() {
                            close(ContextMenuService.menuElement);
                        });
                    }
                }

                function handleClickEvent(event) {
                    if (opened && (event.button !== 2 || event.target !== ContextMenuService.element)) {
                        $scope.$apply(function() {
                            close(ContextMenuService.menuElement);
                        });
                    }
                }

                $document.bind('keyup', handleKeyUpEvent);
                // Firefox treats a right-click as a click and a contextmenu event
                // while other browsers just treat it as a contextmenu event
                $document.bind('click', handleClickEvent);
                $document.bind('contextmenu', handleClickEvent);

                $scope.$on('$destroy', function() {
                    $document.unbind('keyup', handleKeyUpEvent);
                    $document.unbind('click', handleClickEvent);
                    $document.unbind('contextmenu', handleClickEvent);
                });
            }
        };
    }]).name;
})(Entaxy || (Entaxy = {}));
