/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import angular from 'angular';
import {EntityFamily} from '../util/model/entity.model';
import template from './catalog-selector.template.html';
import footerTemplate from './catalog-selector-palette-footer.html';
import { distanceInWordsToNow } from 'date-fns';

const MODULE_NAME = 'brooklyn.composer.component.catalog-selector';
const TEMPLATE_URL = 'blueprint-composer/component/catalog-selector/index.html';
const TEMPLATE_SUBHEAD_URL = 'blueprint-composer/component/catalog-selector/subhead.html';
const TEMPLATE_FOOTER_URL = 'blueprint-composer/component/catalog-selector/footer.html';
const MIN_ROWS_PER_PAGE = 4;

const PALETTE_VIEW_ORDERS = {
        relevance: { id: "relevance", label: "Relevance", field: "relevance" },
        name: { id: "name", label: "Name", field: "displayName" },
        lastUsed: { id: "lastUsed", label: "Recent", field: "-lastUsed" }, 
        bundle: { id: "bundle", label: "Bundle", field: "containingBundle" }, 
        id: { id: "id", label: "ID", field: "symbolicName" }, 
    };

const PALETTE_VIEW_MODES = {
        tiny: { name: "Tiny", classes: "col-xs-2 item-compact", itemsPerRow: 6, rowHeightPx: 75, hideName: true },
        compact: { name: "Compact", classes: "col-xs-3", itemsPerRow: 4 },
        normal: { name: "Normal", classes: "col-xs-4", itemsPerRow: 3 },
        large: { name: "Large", classes: "col-xs-6", itemsPerRow: 2 },
        list: { name: "List", classes: "col-xs-12 item-full-width", itemsPerRow: 1 },
        compactList: { name: "Compact list", classes: "col-xs-12 item-compact-list", itemsPerRow: 1, rowHeightPx: 30 },
    };

// fields in either bundle or type record:
const FIELDS_TO_SEARCH = ['displayName', 'name', 'symbolicName', 'type', 'version', 'containingBundle', 'description', 'displayTags', 'tags', 'supertypes'];

angular.module(MODULE_NAME, [])
    .directive('catalogSelector', catalogSelectorDirective)
    .filter('catalogSelectorSearch', catalogSelectorSearchFilter)
    .filter('catalogSelectorFilters', catalogSelectorFiltersFilter)
    .run(['$templateCache', templateCache]);

export default MODULE_NAME;

export function catalogSelectorDirective() {
    return {
        restrict: 'E',
        templateUrl: function (tElement, tAttrs) {
            return tAttrs.templateUrl || TEMPLATE_URL;
        },
        scope: {
            family: '<',
            onSelect: '&', // action to do when item is selected
            onSelectText: "&?", // function returning text to show in the "on select" button for an item
            iconSelects: '<?',  // boolean whether clicking the icon triggers selection directly or shows popup (false, default) 
            rowsPerPage: '<?',  // optionally show fixed number of rows; unset (default and normal) computes based on available height
            reservedKeys: '<?',
            state: '<?', // for shared state usage
            mode: '@?',  // for use by downstream projects to pass in special modes to do add'l processing / rendering
        },
        controller: ['$scope', '$element', '$timeout', '$q', '$uibModal', '$log', '$templateCache', 'paletteApi', 'paletteDragAndDropService', 'iconGenerator', 'composerOverrides', 'recentlyUsedService', controller],
        link: link,
    };

    function link($scope, $element, attrs, controller) {
        let main = angular.element($element[0].querySelector(".catalog-palette-main"));

        // repaginate when load completes (and items are shown), or it is resized
        $scope.$watchGroup(
            [() => $scope.isLoading, () => main[0].offsetHeight, () => $scope.state.viewMode.name],
            (values) => controller.$timeout(() => repaginate($scope, $element)));
        // also repaginate on window resize
        angular.element(window).bind('resize', () => repaginate($scope, $element));

        $scope.templateUrls = {
            subhead: TEMPLATE_SUBHEAD_URL,
            footer: TEMPLATE_FOOTER_URL
        }
    }

    function controller($scope, $element, $timeout, $q, $uibModal, $log, $templateCache, paletteApi, paletteDragAndDropService, iconGenerator, composerOverrides, recentlyUsedService) {
        this.$timeout = $timeout;

        $scope.viewModes = PALETTE_VIEW_MODES;
        $scope.viewOrders = PALETTE_VIEW_ORDERS;
        if (!$scope.state) $scope.state = {};
        if (!$scope.state.viewMode) $scope.state.viewMode = PALETTE_VIEW_MODES.normal;

        $scope.pagination = {
            page: 1,
            itemsPerPage: $scope.state.viewMode.itemsPerRow * ($scope.rowsPerPage || 1)  // will fill out after load
        };

        $scope.getEntityNameForPalette = function(item, entityName) {
            return (composerOverrides.getEntityNameForPalette ||
                // above can be overridden with function of signature below to customize display name in palette
                function(item, entityName, scope) { return entityName; }
            )(item, entityName, $scope);
        };

        $scope.getPlaceHolder = function () {
            return 'Search';
        };

        $scope.isLoading = true;

        $scope.$watch('search', () => {
            $scope.freeFormTile = {
                symbolicName: $scope.search,
                name: $scope.search,
                displayName: $scope.search,
                supertypes: ($scope.family ? [ $scope.family.superType ] : []),
            };
        });

        $scope.getItems = function (search) {
            let defer = $q.resolve([]);

            switch ($scope.family) {
                case EntityFamily.ENTITY:
                case EntityFamily.SPEC:
                    defer = paletteApi.getTypes({params: {supertype: 'entity', fragment: search}});
                    break;
                case EntityFamily.POLICY:
                    defer = paletteApi.getTypes({params: {supertype: 'policy', fragment: search}});
                    break;
                case EntityFamily.ENRICHER:
                    defer = paletteApi.getTypes({params: {supertype: 'enricher', fragment: search}});
                    break;
                case EntityFamily.LOCATION:
                    defer = paletteApi.getLocations();
                    break;
            }

            return defer.then(data => {
                data = $scope.filterPaletteItemsForMode(data, $scope);
                data.forEach( recentlyUsedService.embellish );
                return data;

            }).catch(error => {
                return [];
            }).finally(() => {
                $scope.isLoading = false;
            });
        };
        function tryMarkUsed(item) {
            try {
                recentlyUsedService.markUsed(item);
            } catch (e) {
                // session storage can get full; usually the culprit is icons not this,
                // but we may wish to clear out old items to ensure we don't bleed here
                $log.warn("Could not mark item as used: "+item, e);
            }
        }
        $scope.mouseInfoPopover = (item, enter) => {
            if ($scope.popoverModal && $scope.popoverVisible && $scope.popover==item) {
                // ignore if modal
                return;
            }
            $scope.popoverModal = false;
            if (enter) {
                $scope.popover = item;
                $scope.popoverVisible = true;
            } else {
                $scope.popoverVisible = false;
            }
        };
        $scope.onClickItem = (item, isInfoIcon, $event) => {
            if (!isInfoIcon && $scope.iconSelects) {
                $scope.onSelectItem(item);
            } else if ($scope.popoverModal && $scope.popoverVisible && $scope.popover == item) {
                $scope.closePopover();
            } else {
                $scope.popover = item;
                $scope.popoverVisible = true;
                $scope.popoverModal = true;
            }
            $event.stopPropagation();
        };
        $scope.closePopover = () => {
            $scope.popoverVisible = false;
            $scope.popoverModal = false;
        };
        $scope.getOnSelectText = function (item) {
            if (!($scope.onSelectText)) return "Select";
            return $scope.onSelectText({item: item});
        };
        $scope.onSelectItem = function (item) {
            $scope.closePopover();
            if (angular.isFunction($scope.onSelect)) {
                tryMarkUsed(item);
                $scope.onSelect({item: item});
            }
            $scope.search = '';
        };
        $scope.onDragItem = function (item, event) {
            let frame = document.createElement('div');
            frame.classList.add('drag-frame');
            event.target.appendChild(frame);
            setTimeout(function() {
                // can remove at end of this cycle, browser will have grabbed its drag image
                frame.parentNode.removeChild(frame);
            }, 0);
            /* have tried many other ways to get a nice drag image;
               this seems to work best, adding an empty div which forces the size to be larger,
               so when grabbing the image it grabs the drop-shadow.
               things that _didn't_ work include:
               - styling event.target now then unstyling (normally this would work, in posts on the web, but it doesn't here; angular?)
               - make a restyled cloned copy offscreen (this comes so close but remote img srcs aren't loaded
             */

            paletteDragAndDropService.dragStart(item);
        };
        $scope.onDragEnd = function (item, event) {
            paletteDragAndDropService.dragEnd();
            tryMarkUsed(item);
        };

        $scope.getOpenCatalogLink = (item) => {
            return "/brooklyn-ui-catalog/#!/bundles/"+item.containingBundle.replace(":","/")+"/types/"+item.symbolicName+"/"+item.version;
        };
        $scope.sortBy = function (order) {
            let newFirst = {};
            if (order) {
                newFirst[order.id] = order;
            }
            $scope.state.currentOrder = Object.assign(newFirst, $scope.state.currentOrder, newFirst);
            $scope.state.currentOrderFields = [];
            $scope.state.currentOrderValues = [];
            Object.values($scope.state.currentOrder).forEach( it => {
                $scope.state.currentOrderValues.push(it);
                $scope.state.currentOrderFields.push(it.field);
            });
        };
        if (!$scope.state.currentOrder) $scope.state.currentOrder = Object.assign({}, PALETTE_VIEW_ORDERS);
        $scope.sortBy();

        $scope.allowFreeForm = function () {
            return [
                EntityFamily.LOCATION
            ].indexOf($scope.family) > -1;
        };
        $scope.isReserved = function () {
            if (!$scope.reservedKeys || !angular.isArray($scope.reservedKeys)) {
                return false;
            }
            return $scope.reservedKeys.indexOf($scope.search) > -1;
        };
        $scope.onImageError = (scope, el, attrs) => {
            $log.warn("Icon for "+attrs.itemId+" at "+angular.element(el).attr("src")+" could not be loaded; generating icon");
            angular.element(el).attr("src", iconGenerator(attrs.itemId));
        };

        // Init
        $scope.items = [];
        function getDisplayTags(tags) {
            if (!tags || !tags.length || !tags.reduce) return tags;
            return tags.reduce((result, tag) => {
                if (!(/[=:\[\]()]/.exec(tag))) {
                    result.push(tag);
                }
                return result;
            }, []);
        }
        $scope.getItems().then((items)=> {
            // add displayTags, as any tag that doesn't contain = : or ( ) [ ]
            // any tag that is an object will be eliminated as it is toStringed to make [ object object ]
            items.forEach(item => {
                if (item.tags) {
                    item.displayTags = getDisplayTags(item.tags);
                }
            });
            $scope.items = items;
        });
        $scope.lastUsedText = (item) => {
            if (item==null) return "";
            let l = (Number)(item.lastUsed);
            if (!l || isNaN(l) || l<=0) return "";
            if (l < 100000) return 'Preselected for inclusion in "Recent" filter.';
            return 'Last used: ' + distanceInWordsToNow(l, { includeSeconds: true, addSuffix: true });
        };

        $scope.showPaletteControls = false;
        $scope.onFiltersShown = () => {
            $timeout( () => {
                // check do we need to show the multiline
                let filters = angular.element($element[0].querySelector(".filters"));
                $scope.$apply( () => $scope.filterSettings.filtersMultilineAvailable = filters[0].scrollHeight > filters[0].offsetHeight + 6 );

                repaginate($scope, $element);
            } );
        };
        $scope.togglePaletteControls = () => {
            $scope.showPaletteControls = !$scope.showPaletteControls;
            $timeout( () => repaginate($scope, $element) );
        };
        $scope.toggleShowAllFilters = () => {
            $scope.filterSettings.showAllFilters = !$scope.filterSettings.showAllFilters;
            $timeout( () => repaginate($scope, $element) );
        };
        $scope.filterSettings = {};

        $scope.filters = [
            { label: 'Recent', icon: 'clock-o', title: "Recently used and standard favorites", limitToOnePage: true,
                filterInit: items => {
                    $scope.recentItems = items.filter( i => i.lastUsed && i.lastUsed>0 );
                    $scope.recentItems.sort( (a,b) => b.lastUsed - a.lastUsed );
                    return $scope.recentItems;
                }, enabled: false },
        ];
        $scope.disableFilters = (showFilters) => {
            $scope.filters.forEach( f => f.enabled = false );
            if (showFilters !== false) {
                $scope.showPaletteControls = true;
            }
        };

        // can be overridden to disable "open in catalog" button
        $scope.allowOpenInCatalog = true;

        // this can be overridden for palette sections/modes which show a subset of the types returned by the server;
        // this is applied when the data is received from the server.
        // it is used by catalogSelectorFiltersFilter;
        $scope.filterPaletteItemsForMode = (items) => items;

        // allow downstream to configure this controller and/or scope
        (composerOverrides.configurePaletteController || function() {})(this, $scope, $element);
    }

    function repaginate($scope, $element) {
        let rowsPerPage = $scope.rowsPerPage;
        if (!rowsPerPage) {
            let palette = angular.element(document.querySelector(".page-main-area"));
            let toolbar = angular.element(document.querySelector(".navbar-mode"));
            let title = 56;
            let header = angular.element($element[0].querySelector(".catalog-palette-header"));
            let footer = angular.element($element[0].querySelector(".catalog-palette-footer"));
            rowsPerPage = Math.max(MIN_ROWS_PER_PAGE, Math.floor((palette[0].offsetHeight - (toolbar[0].offsetHeight + title + header[0].offsetHeight + footer[0].offsetHeight + 32)) / ($scope.state.viewMode.rowHeightPx || 96)));
        }
        $scope.$apply(() => $scope.pagination.itemsPerPage = rowsPerPage * $scope.state.viewMode.itemsPerRow);
    }
}

export function catalogSelectorSearchFilter() {
    return function (items, search) {
        if (search) {
            return items.filter(function (item) {
                item.relevance = 0;
                let wordNum = 0;
                return search.toLowerCase().split(' ').reduce( (found, part) => {
                    wordNum++;
                    let fieldNum = 0;
                    return found &&
                        FIELDS_TO_SEARCH.reduce((match, field) => {
                            if (match) return true;
                            fieldNum++;
                            if (!item.hasOwnProperty(field) || !item[field]) return false;
                            let text = item[field];
                            if (!text.toLowerCase) {
                                text = JSON.stringify(text).toLowerCase();
                            } else {
                                text = text.toLowerCase();
                            }
                            let index = text.indexOf(part);
                            if (index == -1) return false;
                            // found, set relevance -- uses an ad hoc heuristic preferring first fields and short text length,
                            // earlier occurrences and earlier words weighted more highly (smaller number is better)
                            let score = fieldNum * (2 / (1 + wordNum)) * Math.log(1 + text.length * index);
                            /* to debug the scoring function:
                            if (item.symbolicName.indexOf("EIP") >= 0 || item.symbolicName.indexOf("OpsWorks") >= 0) { 
                                console.log(item.symbolicName, ": match", part, "in", field,
                                    "#", fieldNum, wordNum, 
                                    "pos", index, "/", text.length, 
                                    ":", item.relevance, "+=", score);
                            }
                            */
                            item.relevance += score;
                            return true;
                        }, false)
                }, true);
            });
        } else {
            items.forEach( item => item.relevance = 0 );
            return items;
        }
    }
}

export function catalogSelectorFiltersFilter() {
    // compute counts and apply active filters;     
    // this is called by the view after filtering based on search,
    // so filters can adjust based on number of search results
    return function (items, $scope) {
      $scope.itemsBeforeActiveFilters = items;
      $scope.skippingFilters = false; 
      let filters = $scope.filters.filter(f => f.enabled);
      let filtersWithFn = filters.filter(f => f.filterFn);
      if (!filters.length) {
        $scope.itemsAfterActiveFilters = items;
        return items;
      }
      filters.forEach(filter => { if (filter.filterInit) items = filter.filterInit(items); });
      if (filtersWithFn.length) {
        items = items.filter( item => filtersWithFn.some(filter => filter.filterFn(item)) );
      }
      if (!items || !items.length) {
        // if search matches nothing then disable filters
        items = $scope.itemsAfterActiveFilters = $scope.itemsBeforeActiveFilters;
        $scope.skippingFilters = true;
      } else {
        if (filters.find(filter => filter.limitToOnePage)) {
            items = items.splice(0, $scope.pagination.itemsPerPage);
        }  
        $scope.itemsAfterActiveFilters = items;
      }
      return items; 

    }
}

function templateCache($templateCache) {
    $templateCache.put(TEMPLATE_URL, template);
    $templateCache.put(TEMPLATE_SUBHEAD_URL, '');
    $templateCache.put(TEMPLATE_FOOTER_URL, footerTemplate);
}
