(function ($) {
    $.fn.customModal = function (command, data) {
        if (command === "open") {
            this.each((index, value) => {
                openModal($(value), data ? data.closeOtherModals : undefined, data ? data.onOpen: undefined);
            });
        }
        else if (command === "close") {
            this.each((index, value) => {
                closeModal($(value));
            });
        }
        else {
            generateCustomModal(command);
        }
    };

    function openModal($element, closeOtherModals, onOpen, hidden) {
        if (!$element.hasClass("custom-modal") || $element.parent().hasClass("custom-modal-container-open")) return;

        if (closeOtherModals !== false) {
            $(".custom-modal-container-open .custom-modal").each((index, value) => {
                closeModal($(value));
            });
        }


        if (!$element.parent().hasClass("custom-modal-container"))
            $element.wrap("<div class='custom-modal-container'></div>");

        $element.parent().css("display", "none");
        $element.parent().appendTo("body");

        if (hidden) return;

        $element.parent().addClass("custom-modal-container-open");
        $element.parent().css("display", "block");
        $element.parent().animate({
            opacity: "1"
        }, 500, function () {
            $element.trigger("custom-modal-opened");
        });
    }

    function closeModal($element) {
        if (!$element.hasClass("custom-modal") || !$element.parent().hasClass("custom-modal-container-open")) return;

        $element.parent().removeClass("custom-modal-container-open");
        $element.parent().animate({
            opacity: "0"
        }, 500, function () {
            $element.trigger("custom-modal-closed");
            $element.parent().css("display", "none");
            $element.css("left", "").css("top", "");
        });
    }

    function generateCustomModal(data) {
        if ($("#" + data.id).length > 0) {
            openModal($("#" + data.id), data.closeOtherModals, data.onOpen);
            return;
        }
        if (!paw.utils.value.isSet(data.draggable)) {
            data.draggable = true;
        }

        let $modal = $("<div class='custom-modal'></div>");
        data.title = generateTitle(data.type, data.localization, data.title, data.customTitle);
        if (data.id) $modal.prop("id", data.id);
        if (data.class) $modal.addClass(data.class);
        if (data.type !== "modal") $modal.addClass("custom-modal-popup");
        if (data.width && data.width.length > 1 && data.width.substr(-1) === "%") $modal.css("width", data.width);
        if (data.minWidth) $modal.css("min-width", data.minWidth);
        if (data.maxWidth) $modal.css("max-width", data.maxWidth);
        if (data.height && data.height.length > 1 && data.height.substr(-1) === "%") $modal.css("height", data.height);
        if (data.minHeight) $modal.css("min-height", data.minHeight);
        if (data.maxHeight) $modal.css("max-height", data.maxHeight);

        $modal.on("custom-modal-closed", function () {
            if (data.onClose) data.onClose();

            if (data.destroyOnClose !== false) {
                $(this).parent().remove();
            }
        });

        $modal.on("custom-modal-opened", function () {
            if (data.onOpen) data.onOpen();
        });

        let $modalContent = $("<div class='custom-modal-content'></div>");
        $modalContent.append(generateTypeIcon(data.type));
        $modalContent.append(generateCustomModalHeader(data.title, data.showCloseButton, data.help, data.draggable));
        $modalContent.append(generateCustomModalBody(data.text, data.content, data.modalBodyClass));
        $modalContent.append(generateCustomModalFooter(data.buttons));
        $modal.append($modalContent);

        let isCustomModalResizerMouseDown = false;
        if (data.resizable === true) {
            let $modealResizer = $("<div class='custom-modal-resizer'></div>");
            $modealResizer.on("mousedown", function () {
                isCustomModalResizerMouseDown = true;
                $("body").css("user-select", "none");
            });
            $modealResizer.on("mouseup", function () {
                isCustomModalResizerMouseDown = false;
                $("body").css("user-select", "auto");
            });
            $(window).on("mouseup", function () {
                isCustomModalResizerMouseDown = false;
                $("body").css("user-select", "auto");
            });
            $(window).on("mousemove", function (e) {
                if (!isCustomModalResizerMouseDown) return;

                let screenWidth = $(window).width();
                let screenHeight = $(window).height();
                let centerPoint = { x: screenWidth / 2, y: screenHeight / 2 };
                let mousePoint = { x: e.pageX + ($modealResizer.width() / 2), y: e.pageY + ($modealResizer.height() / 2) };

                let xPercent = (100 / screenWidth) * ((mousePoint.x - centerPoint.x) * 2);
                let yPercent = (100 / screenHeight) * ((mousePoint.y - centerPoint.y) * 2);

                $modal.css({ "min-width": "300px", "max-width": "99%", "min-height": "300px", "max-height": "99%", "width": xPercent + "%", "height": yPercent + "%" });

            });
            $modal.append($modealResizer);
        }

        if (data.draggable) {
            let $draggableArea = $modal.find(".custom-modal-draggable-area");
            let isDragging = false;
            let currentDraggingCursorPoint = undefined;

            $draggableArea.on("mousedown", function (e) {
                if ($modal.attr('data-drag-lock') === 'true') {
                    return;
                }
                isDragging = true;
                currentDraggingCursorPoint = { x: e.pageX, y: e.pageY };
            });
            $draggableArea.on("mouseup", function () {
                if ($modal.attr('data-drag-lock') === 'true') {
                    return;
                }
                isDragging = false;
            });
            $(window).on("mouseup", function () {
                isDragging = false;
            });
            $(window).on("mousemove", function (e) {
                if (!isDragging) return;

                let currentCursorPoint = { x: e.pageX, y: e.pageY };
                $modal.css("left", parseFloat($modal.css("left")) + currentCursorPoint.x - currentDraggingCursorPoint.x)
                    .css("top", parseFloat($modal.css("top")) + currentCursorPoint.y - currentDraggingCursorPoint.y);

                currentDraggingCursorPoint = currentCursorPoint;
            });
        }

        openModal($modal, data.closeOtherModals, data.onOpen, data.openOnCreate === false);

        if (data.onCreated) data.onCreated();
    }

    function generateTitle(type, localization, title, customTitle) {
        if (customTitle || !type || type === "modal") return title;

        if (!localization || !localization[type])
            return $("#custom-modal-" + type).length === 0 ? type[0].toUpperCase() + type.slice(1) : $("#custom-modal-" + type).val();

        return localization[type];
    }

    function generateTypeIcon(type) {
        let $type = "";
        if (type && type !== "modal")
            $type = $("<div class='custom-modal-type-icon custom-modal-" + type + "-icon'></div>");

        return $type;
    }

    function generateCustomModalHeader(title, showCloseButton, help, draggable) {
        let $header = $("<div class='custom-modal-header " + (draggable ? "custom-modal-draggable-area" : "") + "'></div>");

        if (title) $header.append("<h3 class='custom-modal-title'>" + title + "</h3>");

        let $iconTray = $("<div class='custom-modal-icon-tray'></div>");

        if (help) {
            let $helpButton = $("<span class='custom-modal-icon fa fa-question' title='" + $("#checkInstructionsLoc").val() + "'></span>");
            $helpButton.on("click", function () {
                if (typeof help === "function") {
                    help();
                }
                else {
                    let win = window.open(help, '_blank');
                    win.focus();
                }
            });
            $iconTray.append($helpButton);
        }

        if (showCloseButton !== false) {
            let $closeButton = $("<span class='custom-modal-icon fa fa-times'></span>");
            $closeButton.on("click", function () {
                closeModal($(this).closest(".custom-modal"));
            });
            $iconTray.append($closeButton);
        }

        $header.append($iconTray);

        return $header;
    }

    function generateCustomModalBody(text, content, modalBodyClass) {
        let $body = $("<div class='custom-modal-body " + modalBodyClass + "'></div>");

        if (content) {
            $bodyContent = $(content);
        }
        else {
            $bodyContent = $("<div class='custom-modal-body-content'></div>");
            $bodyContent.append("<span>" + text + "</span>");
        }

        $body.append($bodyContent);

        return $body;
    }

    function generateCustomModalFooter(buttons) {
        let $footer = $("<div class='custom-modal-footer'></div>");

        if (buttons && buttons.length > 0)
            $footer.append(generateButtons(buttons));
        else
            $footer.addClass("hidden");

        return $footer;
    }

    function generateButtons(buttons) {
        if (!buttons) return;

        $buttons = $("<div></div>");
        buttons.forEach(button => {
            if (button.content) {
                $buttons.append($(button.content));
            }
            else {
                let $button = $("<button type='button' class='m-l-xs btn " + (button.class ? button.class : "") + "' " + (button.disabled === true ? "disabled" : "") + "></button>");
                $button.addClass("btn-" + button.type);
                $button.append("<i class='" + (button.icon ? button.icon : "") + "'></i>");
                $button.append("<span class='" + (button.text ? "m-l-xs" : "") + "'>" + (button.text ? button.text : "") + "</span>");

                $button.on("click", async function () {
                    let actionSuccess = true;
                    if (button.action) {
                        let originalIcons = $button.find("i").prop("class");
                        $button.find("i").prop("class", "fa fa-spin fa-spinner");

                        try {
                            await button.action();
                        } catch (err) {
                            actionSuccess = false;
                        }
                        finally {
                            $button.find("i").prop("class", originalIcons);
                        }
                    }

                    if (actionSuccess === true && button.closeOnAction === true) {
                        closeModal($(this).closest(".custom-modal"));
                    }
                });

                $buttons.append($button);
            }
        });

        return $buttons;
    }
}(jQuery));
