// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
/**
 * @type {MasterPaneView}
 */
define(['hp/presenter/MasterPanePresenter',
    'hp/view/MasterTableView',
    'hp/view/MasterGridView',
    'hp/view/SearchBoxView',
    'hp/view/MasterErrorView',
    'hp/core/LinkTargetBuilder',
    'hp/core/Localizer',
    'hp/core/Router',
    'hp/core/Style',
    'hp/core/UrlFragment',    
    'text!hpPages/core/master_sub_nav.html',
    'text!hpPages/core/master_header.html',
    'text!hpPages/core/no_details.html',
    'text!hpPages/core/no_items.html',
    'jquery',
    'hp/lib/jquery.hpSelect',
    'hp/lib/jquery.hpEllipsis',
    'hp/lib/jquery.hpCollapsible'],
function (MasterPanePresenter, MasterTableView, MasterGridView, searchBoxView, errorView,
    linkTargetBuilder, localizer, router, style, urlFragment,
    subnavHtml, headerHtml, noDetailsHtml, noItemsHtml) {
"use strict";

    var MasterPaneView = (function () {

        // consts can go here
        var MASTER_PANE = '.hp-master-pane';
        var DETAILS_PANE = '.hp-details-pane';
        var TABLE_WRAPPER = '.dataTables_wrapper';
        var TABLE = '.hp-master-table';
        var GRID = '.hp-master-grid';
        var TITLE = '.hp-master-header .hp-master-title';
        var HEADER = MASTER_PANE + ' .hp-master-header';
        var COUNT = '.hp-page-item-count';
        var MATCH_COUNT_CLASS_NAME = 'hp-master-match-count';
        var MATCH_COUNT = '.' + MATCH_COUNT_CLASS_NAME;
        var FILTERBAR_CONTROL = '.hp-filterbar-control';
        var FILTERBAR_RESET_FILTERS = '.hp-master-filter .hp-filter-reset';
        var SUBNAV_RESET_FILTERS = '.hp-sub-nav .hp-filter-reset';
        var ALL_RESET_FILTERS = SUBNAV_RESET_FILTERS + ', ' + FILTERBAR_RESET_FILTERS; 
        var FILTERBAR = '.hp-master-filter';
        var FILTER = '.hp-sub-nav .hp-filter[data-filter-property], .hp-master-filter .hp-filter[data-filter-property]';
        var META_FILTER = '.hp-sub-nav .hp-meta-filter, .hp-master-filter .hp-meta-filter';
        var SORTER = '#hp-master-sort';
        var EMPTY_MESSAGE = DETAILS_PANE + ' .hp-empty-message';
        var ACTIVE = 'hp-active';
        var FILTERBAR_OPEN = 'hp-filterbar-open';

        /**
         * @constructor
         */
        function MasterPaneView() {

            //
            // private class instance variables
            //
            var presenter = new MasterPanePresenter();
            var page = null;
            var globalView = true;
            var table = null;
            var grid = null;
            var active = false;
            var activeView = false;
            var itemOk = true;
            var noDetails = $(noDetailsHtml);
            var noItems = $(noItemsHtml);
            var relayoutTimer;

            function fireRelayout() {
                // we delay so any CSS animation can finish
                setTimeout(function () {
                    $(DETAILS_PANE, page).css('left',
                        $(MASTER_PANE, page).outerWidth());
                    $(page).trigger('relayout');
                }, style.animationDelay());
            }

            function resizeFilterbar() {
                if ($(page).hasClass(FILTERBAR_OPEN)) {
                    // adjust filter bar width based on contents
                    var filterWidth = 200;
                    $(FILTERBAR + ' > *', page).each(function (index, element) {
                        filterWidth = Math.max(filterWidth,
                            $(element).outerWidth(true));
                    });
                    $(FILTERBAR, page).css('width', filterWidth);
                    $(FILTERBAR, page).next().css('left', filterWidth + 15);
                    fireRelayout();
                }
            }

            function closeFilterbar() {
                $('.hp-sub-nav .hp-page-label', page).after(
                    $(FILTERBAR + ' .hp-master-referrer', page));
                if ($('.hp-sub-nav .hp-master-referrer', page).length > 0) {
                    $('.hp-sub-nav .hp-master-referrer', page).after(
                        $(FILTERBAR + ' .hp-filter', page).removeClass('hp-active hp-pinned'));
                } else {
                    $('.hp-sub-nav .hp-page-label', page).after(
                        $(FILTERBAR + ' .hp-filter', page).removeClass('hp-active hp-pinned'));
                }
                $(FILTERBAR, page).css('width', '');
                $(FILTERBAR, page).next().css('left', '');
                $(SUBNAV_RESET_FILTERS).show();
                $(page).removeClass(FILTERBAR_OPEN);
                fireRelayout();
            }

            function openFilterbar() {
                $(page).addClass(FILTERBAR_OPEN);
                $(SUBNAV_RESET_FILTERS).hide();
                $(FILTERBAR, page).append($('.hp-sub-nav .hp-master-referrer', page));
                $(FILTERBAR, page).append(
                    $('.hp-sub-nav .hp-filter', page).addClass('hp-active hp-pinned'));
                resizeFilterbar();
            }

            function toggleFilterbar() {
                if ($(FILTERBAR, page).length > 0 &&
                    ! $(page).hasClass(FILTERBAR_OPEN)) {
                    openFilterbar();
                } else {
                    closeFilterbar();
                }
            }

            function onResetFilters() {
                presenter.resetFilters();
            }

            function onReferrerChange(resource) {
                $('.hp-master-referrer', page).remove();
                if (resource) {
                    var elem = $('<div></div>').addClass('hp-master-referrer');
                    
                    $('<label></label>')
                        .text(localizer.getString('core.master.filters.referrerLabel'))
                        .appendTo(elem);
                    
                    var link = linkTargetBuilder.makeLink(resource.name, resource.uri);
                    // is it really a link? 
                    if (link.indexOf("<a") === -1) {
                        elem.text(link);
                    }
                    else {
                        elem.append($(link));
                    }

                    elem.append($('<a></a>').addClass('hp-close').
                        attr('href', '#' + presenter.getReferrerClearLocation()));
                    if (resource.name.length > 20) {
                        $('a:first-child', elem).hpEllipsis();
                    }
                    
                    if ($(FILTERBAR, page).length > 0 &&
                        $(page).hasClass(FILTERBAR_OPEN)) {
                        $(FILTERBAR + ' header', page).after(elem);
                    } else {
                        $('.hp-sub-nav .hp-page-label', page).after(elem);
                    }
                }
            }

            function onPropertyFilterChange(ev, value) {
                var name = $(this).attr('data-filter-property');
                if (name) {
                    presenter.setFilterValue(name, value);
                }
            }
            
            function onMetaFilterChange(ev, value) {
                var query = $(META_FILTER, page).find('li[data-id="' + value + '"]').
                    attr('data-query');
                presenter.setMetaFilter(query);
            }

            function onSortChange(ev, value) {
                presenter.setSort(value, 'asc');
            }
            
            // @private
            // Update the match count with the latest results from the index
            // @param {Object} data The results from an index request
            function updateMatchCount(indexResults) {
                if ((!indexResults.filter.data.hasOwnProperty('userQuery')) &&
                    (!indexResults.filter.data.hasOwnProperty('associationName'))) {
                    $(MATCH_COUNT, page).hide();
                    return;
                }
                      
                if ((undefined === indexResults.total) ||
                    (undefined === indexResults.unFilteredTotal)) {
                    $(MATCH_COUNT, page).hide();
                    return;
                }
                
                var matchText;
                if (indexResults.total === 1) {
                    matchText = localizer.getString('core.master.filters.matchCount',
                        [indexResults.unFilteredTotal]);
                } else {
                    matchText = localizer.getString('core.master.filters.matchesCount',
                        [indexResults.total, indexResults.unFilteredTotal]);
                }
                $(MATCH_COUNT, page).text(matchText);
                $(MATCH_COUNT, page).show();
            }

            /**
             * @private
             * @param {Object} data the IndexResults
             */
            function onIndexResultsChange(indexResults) {
                if (page) {
                    $(MASTER_PANE + ' #hp-no-items', page).remove();
                    $(TITLE, page).text(presenter.getHeaderTitle());
                    if (indexResults) {
                        $(COUNT, page).text(indexResults.total);
                        $(EMPTY_MESSAGE, page).remove();
                        if (indexResults.total === 0) {
                            $(DETAILS_PANE, page).addClass('hp-empty').
                                append('<div class="hp-empty-message">' +
                                    presenter.getEmptyMessage(indexResults) + '</div>');
                            $(MASTER_PANE, page).addClass('hp-empty');
                        } else {
                            if (itemOk) {
                                $(DETAILS_PANE, page).removeClass('hp-empty');
                                $(EMPTY_MESSAGE, page).remove();
                            }
                            $(MASTER_PANE, page).removeClass('hp-empty');
                        }
                        updateMatchCount(indexResults);
                    }
                }
            }

            function onIndexResultsError(errorInfo) {
                if (page) {
                    $(MASTER_PANE + ' #hp-no-items', page).remove();
                    $(MASTER_PANE, page).append(noItems);
                }
            }

            function onValidSelection() {
                itemOk = true;
                if (page) {
                    $(DETAILS_PANE, page).removeClass('hp-empty');
                    $(EMPTY_MESSAGE, page).remove();
                    $(DETAILS_PANE + ' #hp-no-details', page).remove();
                }
            }

            function onInvalidSelection(selection) {
                itemOk = false;
                if (page) {
                    $(DETAILS_PANE + ' #hp-no-details', page).remove();
                    $(DETAILS_PANE, page).addClass('hp-empty').append(noDetails);
                    $('.hp-collapsible', noDetails).hide();
                }
            }

            function onSelectionChange(selection) {
                if (page && globalView) {
                    searchBoxView.setLocalSearchText(presenter.getSearchText());
                }
            }

            function onFilterChange(filter) {
                if (page) {
                    // see if a meta filter matches the query string, must be exact for now
                    var metaOption = null;
                    if ($(META_FILTER, page).length > 0) {
                        var metaOption = $(META_FILTER, page).find(' li[data-query="' +
                            presenter.getSearchText() + '"]');
                        if (metaOption.length > 0) {
                            $(META_FILTER, page).hpSelect('set',
                                metaOption.attr('data-id'));
                        } else {
                            $(META_FILTER, page).hpSelect('set',
                                localizer.getString('fs.activity.filter.meta.custom'));
                        }
                    }
                    // disable reset if we are on the default meta filter
                    $(ALL_RESET_FILTERS, page).toggleClass('hp-disabled',
                        (metaOption !== null && metaOption.hasClass('hp-default')));
                    
                    $(FILTER, page).each(function (index, elem) {
                        if (! $(elem).hasClass('.hp-meta-filter')) {
                            var name = $(elem).attr('data-filter-property');
                            var value = presenter.getFilterValue(name);
                            $(elem).hpSelect('set', value);
                        }
                    });
                    
                    urlFragment.replaceHrefParametersFromFragment($(DETAILS_PANE, page), filter.updateLocation(router.location()));
                    if (globalView) {
                        searchBoxView.setLocalSearchText(presenter.getSearchText());
                    }
                }
            }

            function onClickTable() {
                if (table !== activeView) {
                    if (grid === activeView) {
                        grid.pause();
                        $(GRID, page).removeClass(ACTIVE);
                        $('.hp-master-grid-view', page).removeClass(ACTIVE);
                    }
                    $('.hp-master-table-view', page).addClass(ACTIVE);
                    $(TABLE_WRAPPER, page).addClass(ACTIVE);
                    if (active) {
                        table.resume();
                    }
                    activeView = table;
                    presenter.renotify(true);
                }
            }

            function onClickGrid() {
                if (grid !== activeView) {
                    if (table === activeView) {
                        table.pause();
                        $(TABLE_WRAPPER, page).removeClass(ACTIVE);
                        $('.hp-master-table-view', page).removeClass(ACTIVE);
                    }
                    $('.hp-master-grid-view', page).addClass(ACTIVE);
                    $(GRID, page).addClass(ACTIVE);
                    if (active) {
                        grid.resume();
                    }
                    activeView = grid;
                    presenter.renotify(true);
                }
            }

            function onResizeDrag(event, ui) {
                var masterPane = $(MASTER_PANE, page);
                // what column sizes should we align to?
                var quanta = Math.floor($(window).width() / 12);
                var newWidth = Math.max(200, ui.size.width);
                newWidth = quanta * Math.floor((newWidth + (quanta / 2)) / quanta);

                masterPane.addClass('hp-resized');
                // adjust width since master pane is box sized for content-box
                // clear height that ui-resizable set
                masterPane.css({'width': newWidth  -
                    (masterPane.outerWidth() - masterPane.width()), 'height': ''});
                $(DETAILS_PANE, page).css('left', newWidth);
                // we've done the panes, re-layout the content when animation finishes
                clearTimeout(relayoutTimer);
                relayoutTimer = setTimeout(function () {
                    $(page).trigger('relayout');
                }, style.animationDelay());
            }

            this.enableUpdates = function () {
                presenter.enableUpdates();
            };

            this.disableUpdates = function () {
                presenter.disableUpdates();
            };

            /**
             * @public
             * Stop the timer polling of the index service.
             */
            this.pause = function () {
                if (active) {
                    active = false;
                    presenter.pause();
                    presenter.off("indexResultsChange", onIndexResultsChange);
                    presenter.off("indexResultsError", onIndexResultsError);
                    presenter.off("selectionChange", onSelectionChange);
                    presenter.off("invalidSelection", onInvalidSelection);
                    presenter.off("validSelection", onValidSelection);
                    presenter.off("referrerChange", onReferrerChange);
                    presenter.off("filterChange", onFilterChange);
                    if (activeView) {
                        activeView.pause();
                    }
                    errorView.pause();
                    $(COUNT, page).text('');
                    $(MATCH_COUNT, page).hide();
                }
            };

            /**
             * @public
             * Resume the timer polling of the index service.
             */
            this.resume = function () {
                if (! active) {
                    active = true;
                    presenter.on("indexResultsChange", onIndexResultsChange);
                    presenter.on("indexResultsError", onIndexResultsError);
                    presenter.on("selectionChange", onSelectionChange);
                    presenter.on("invalidSelection", onInvalidSelection);
                    presenter.on("validSelection", onValidSelection);
                    presenter.on("referrerChange", onReferrerChange);
                    presenter.on("filterChange", onFilterChange);
                    if (activeView) {
                        activeView.resume();
                    }
                    // Resume the presenter after everyone is listening again.
                    // This ensures they hear about the latest state.
                    presenter.resume();
                    errorView.resume();

                    fireRelayout(); // in case window was resized while we were away
                    setTimeout(resizeFilterbar, 400);                   
                }
            };

            /**
             * @public
             * Intialize the view.
             */
            this.init = function (args) {
                
                page = args.page;

                localizer.localizeDom(noDetails);
                localizer.localizeDom(noItems);

                var categoryLabel = linkTargetBuilder.categoryLabel(args.resource.category).
                    toLowerCase();
                $('h1', noItems).
                    text(localizer.getString('core.noItems.header', [categoryLabel]));
                
                var defaultMetaQuery =
                    $('.hp-filters .hp-meta-filter li.hp-default', page).
                        attr('data-query');
                if (defaultMetaQuery) {
                    args = $.extend({defaultMetaQuery: defaultMetaQuery}, args);
                }
                    
                presenter.init(args);
                errorView.init(presenter);

                if (page) {
                    globalView = !(args.contextSensitive);
                    if (globalView && $('.hp-sub-nav', page).length === 0) {
                        $(page).prepend($(subnavHtml));
                    }
                    if (globalView &&
                        $('.hp-sub-nav ' + MATCH_COUNT, page).length === 0) {
                        var matchedCount = $('<div></div>')
                            .addClass(MATCH_COUNT_CLASS_NAME)
                            .hide();
                        if ($('.hp-sub-nav .hp-sidebar-control', page).length > 0) {
                            $('.hp-sub-nav .hp-sidebar-control', page).before(matchedCount);
                        } else {
                            $('.hp-sub-nav', page).append(matchedCount);
                        }
                    }

                    $('.hp-sub-nav .hp-select.hp-filter', page).hpSelect();
                    $('.hp-master-filter .hp-select.hp-filter', page).hpSelect();
                    $(SORTER, page).hpSelect();
                    $(DETAILS_PANE, page).addClass('hp-empty');
                    if (globalView && $(HEADER, page).length === 0) {
                        $('.hp-master-pane', page).prepend($(headerHtml));
                    }
                    if (args.addLink) {
                        $(HEADER + ' .hp-master-add', page).
                            append($(args.addLink).addClass('hp-button hp-secondary'));
                    }

                    // Allow resizing the master pane if not full
                    if (globalView && $('.hp-master-full', page).length === 0) {
                        $('.hp-master-pane', page).resizable({handles : 'e',
                            resize: onResizeDrag, zIndex: 0});
                    }

                    $(FILTERBAR_CONTROL, page).on('click', toggleFilterbar);
                    $(FILTER + ':not(' + META_FILTER + ')', page).on('change', onPropertyFilterChange);
                    $(META_FILTER, page).on('change', onMetaFilterChange);
                    $(SORTER, page).on('change', onSortChange);
                    
                    $(ALL_RESET_FILTERS, page).on('click', onResetFilters);
                }

                if (args.dataTableOptions &&
                    (args.table || (page && $(TABLE, page).length > 0))) {
                    table = new MasterTableView();
                    table.init(presenter, args);
                }

                if (args.grid || (page && $(GRID, page).length > 0)) {
                    grid = new MasterGridView();
                    grid.init(presenter, args);
                }

                if (page && table && grid) {
                    $('.hp-master-view', page).addClass(ACTIVE);
                    $('.hp-master-table-view', page).click(onClickTable);
                    $('.hp-master-grid-view', page).click(onClickGrid);
                    onClickTable();
                } else if (table) {
                    onClickTable();
                } else if (grid) {
                    onClickGrid();
                }

                this.resume();
            };
        }

        return MasterPaneView;

    }());

    return MasterPaneView;
});
