/*global Granite, DQM, document*/
/**
 * Interactions
 *
 * Responsibilities:
 *   - attaches event handlers after successful construction of the side-panel
 *     - window resize handling
 *     - sidePanel resize handling
 *     - overlay clicks
 *     - accordion items clicks
 *   - removes event handlers on side-panel deconstruction
 */
(function ($, ns, dqm, channel) {

    var self = {
        $overlayWrapper: $("#OverlayWrapper")
    };

    function getEditable(event) {
        return ns.editables.find($(event.currentTarget).data("path"))[0];
    }

    function getRailElement() {
        if (!self.$rail) {
            self.$rail = $("#dqm-validation-rail");
        }
        return self.$rail;
    }

    /**
     * Sets sidePanel width to enable Checkpoint name shortening
     * if width of the Checkpoint name is greater than width of the side-panel.
     *
     * Adds title attribute to the shortened Checkpoint names.
     *
     * @param reload - forces look-up for #SidePanel element
     */
    function setAccordionWidth(reload) {
        var $rail = getRailElement(),
            sidePanelWidth;
        if (!self.$sidePanel || reload) {
            self.$sidePanel = $("#SidePanel");
            self.$resizable = $rail.find(".dqm-resizable-container");
        }
        sidePanelWidth = self.$sidePanel.width();
        // 48 - width of tab bar; 32 - padding around accordions; 2 - borders
        self.$resizable.css({"max-width": (sidePanelWidth - 48 - 32 - 2) + "px"});
        $rail.find(".coral3-Accordion-header").each(function () {
            var $el = $(this);
            if (this.scrollWidth > this.offsetWidth) {
                this.title = $el.parent().data("issue-name");
            } else {
                this.removeAttribute("title");
            }
        });
        setMarkupInspectionWidth(sidePanelWidth);
    }

    function collapseAccordions() {
        self.$highlightedIssues.find(".coral3-Accordion-item").prop("selected", false);
    }

    /**
     * Scrolls to the Checkpoint name of the first highlighted component
     *
     * @param $el - element to scroll to
     */
    function scrollToHighlightedCheckpoint($el) {
        // setTimeout to wait for any not highlighted accordions to be closed
        setTimeout(function () {
            var offset = $el.parents(".coral3-Accordion-item").get(0).offsetTop;
            $(".dqm-resizable-container").animate({scrollTop: offset}, 250);
        }, 250);
    }

    /**
     * Allows for bi-directional interaction between side-panel and content-frame
     *
     * @param path - path of the editable which overlay was clicked in content-frame
     * @param showInContent
     */
    function handleComponentItemsSelection(path, showInContent) {
        var collapsed,
            shouldShowComponent;
        getRailElement().find(".coral3-Accordion-content li").each(function (i, el) {
            var $el = $(el);
            if (path && $el.data("editable-path") === path) {
                if (!self.$highlightedIssues) {
                    self.$highlightedIssues = $("#dqm-validation-highlighted-issues");
                }
                if (!collapsed) {
                    collapseAccordions();
                    scrollToHighlightedCheckpoint($el);
                    collapsed = true;
                }
                $el.closest(".coral3-Accordion-item").prop("selected", true);
                $el.addClass("is-selected");
                shouldShowComponent = true;
            } else {
                $el.removeClass("is-selected");
            }
        });
        if (showInContent && shouldShowComponent) {
            showComponent(path, !ns.device.isDesktop());
        }
    }

    /**
     * Set. new width for markup inspection dialog if exists.
     */
    function setMarkupInspectionWidth(width) {
        if (self.$markupDialog) {
            self.$markupDialog.width($(window).width() - (width ? width : self.$sidePanel.width()));
        }
    }

    function closeMarkupInspection() {
        if (self.$markupDialog && self.$markupDialog.get(0).offsetParent != null) {
            self.$markupDialog.hide();
        }
    }

    /**
     * Scrolls to component in content-frame after selecting an accordion item in side-panel
     *
     * @param path - path of the editable
     * @param closeSidePanel - flag which determine if side-panel should be closed upon selecting an accordion item in side-panel
     *                         set to true for mobile devices
     */
    function showComponent(path, closeSidePanel) {
        var editable = ns.editables.find(path)[0];
        if (editable && editable.overlay) {
            ns.selection.deactivateCurrent();
            closeMarkupInspection();
            scrollToComponent(editable.overlay.dom.get(0), closeSidePanel);
            ns.selection.select(editable);
            ns.selection.activate(editable);
        }
    }

    function scrollToComponent(dom, closeSidePanel) {
        if (closeSidePanel) {
            channel.on("cq-sidepanel-aftertoggle.dqmvalidation", $.debounce(100, function () {
                dom.scrollIntoView();
                channel.off("cq-sidepanel-aftertoggle.dqmvalidation");
            }));
            ns.ui.SidePanel.close(true);
        } else {
            dom.scrollIntoView();
        }
    }

    function toggleLoading(loading) {
        self.$markupIssueLoader.toggle(loading);
        self.$markupFrame.css("visibility", loading ? "hidden" : "visible");
    }

    function createInspectUrl($inspectButton) {
        var inspectUrl = $inspectButton.data("url"),
            componentIndex = $inspectButton.parent().find("li.is-selected").data("inspect-markup-index");
        return inspectUrl + (componentIndex ? "&cmpIdx=" + componentIndex + "#" + componentIndex : "");
    }

    /**
     * Creates a dialog displayed above content-frame containing an iframe with the markup inspection
     * @param event
     */
    function inspectMarkup(event) {
        var issueName = $(event.currentTarget).data("issue-name"),
            inspectUrl = createInspectUrl($(event.currentTarget)),
            fullscreenMarkup,
            toggleInspection;
        if (!self.$markupFrame) {
            fullscreenMarkup = dqm.templates.markupInspection;
            $("#Content").append($(fullscreenMarkup({inspectUrl: inspectUrl, issueName: issueName})));
            self.$markupDialog = $("#dqm-markup-inspection-dialog");
            self.$markupFrame = self.$markupDialog.find("iframe");
            self.$markupIssueName = self.$markupDialog.find("h2");
            self.$markupIssueLoader = self.$markupDialog.find("#dqm-markup-inspection-loader");
            setMarkupInspectionWidth();
        } else {
            toggleInspection = true;
            if (self.$markupFrame.attr("src") !== inspectUrl) {
                toggleLoading(true);
                self.$markupIssueName.text(issueName);
                self.$markupFrame.attr("src", inspectUrl);
            } else {
                toggleInspection = self.$markupDialog.get(0).offsetParent == null;
            }
            self.$markupDialog.toggle(toggleInspection);
        }
        self.$markupFrame.one("load", function () {
            toggleLoading(false);
        });
    }

    /**
     * AEM issue workaround - popovers are not closed on overlay click in content frame
     */
    function forceHidePopovers() {
        getRailElement().find(".coral3-Popover.is-open").each(function (i, el) {
            var $el = $(el);
            $el.removeClass("is-open");
            $el.removeAttr("open");
        });
    }

    $(document).on("click", ".dqm-markup-inspection-cancel", function (e) {
        e.preventDefault();
        self.$markupDialog.hide();
    });

    dqm.bindListeners = function () {

        // override hover trigger for dqm.Validatables
        if (!ns.device.isIpad) {
            self.$overlayWrapper.on("mouseover.dqmvalidation mouseout.dqmvalidation",
                ".cq-Overlay--component", function (event) {
                    var editable = getEditable(event);
                    channel.trigger($.Event("cq-overlay-hover", {
                        inspectable: editable,
                        editable: editable,
                        originalEvent: event
                    }));
                });
        }

        channel.on("dqm-issues-loaded", function () {
            setAccordionWidth(true);
        });
        channel.on("click", ".dqm-markup-inspection", inspectMarkup);
        channel.on("cq-overlay-click.dqmvalidation cq-overlay-outside-click.dqmvalidation", function (event) {
            var path = event.editable ? event.editable.path : undefined;
            forceHidePopovers();
            handleComponentItemsSelection(path);
        });
        channel.on("click", ".dqm-show-component", function (event) {
            var path = $(event.currentTarget).data("editable-path");
            handleComponentItemsSelection(path, true);
        });
        channel.on("cq-sidepanel-resized.dqmvalidation", $.debounce(100, true, setAccordionWidth));
    };

    dqm.unbindListeners = function () {
        channel.off("cq-overlay-click.dqmvalidation cq-overlay-outside-click.dqmvalidation");
        channel.off("cq-sidepanel-resized.dqmvalidation");
	channel.off("click", ".dqm-markup-inspection", inspectMarkup);
        self.$overlayWrapper.off("mouseover.dqmvalidation mouseout.dqmvalidation");
    };

}(jQuery, Granite.author, DQM, jQuery(document)));
