/*
 * 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';

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

export function catalogSelectorDirective() {
    return {
        restrict: 'E',
        scope: {
            family: '<',
            onSelect: '&',
            itemsPerPage: '<',
            reservedKeys: '<?',
            mode: '@?',  // for use by downstream projects to pass in special modes
        },
        template: template,
        controller: ['$scope', '$element', '$q', '$uibModal', '$log', '$templateCache', 'paletteApi', 'paletteDragAndDropService', 'iconGenerator', 'composerOverrides', controller]
    };
}

export function catalogSelectorSearchFilter() {
    return function (items, search) {
        if (search) {
            return items.filter(function (item) {
                return search.toLowerCase().split(' ').reduce( (found, part) => 
                    found &&
                    FIELDS_TO_SEARCH
                        .filter(field => item.hasOwnProperty(field) && item[field])
                        .reduce((match, field) => {
                            if (match) return true;
                            let text = item[field];
                            if (!text.toLowerCase) {
                                text = JSON.stringify(text).toLowerCase();
                            } else {
                                text = text.toLowerCase();
                            }
                            return match || text.indexOf(part) > -1;
                        }, false)
                , true);
            });
        } else {
            return items;
        }
    }
}

export function catalogSelectorSortFilter($filter) {
    return function (items, family) {
        return items.sort(function (left, right) {
            let nameLeft;
            let nameRight;
            if (family) {
                switch (family) {
                    case EntityFamily.ENTITY:
                    case EntityFamily.SPEC:
                    case EntityFamily.POLICY:
                    case EntityFamily.ENRICHER:
                    case EntityFamily.LOCATION:
                        nameLeft = $filter('entityName')(left);
                        nameRight = $filter('entityName')(right);
                        break;
                }
            }

            if (!nameLeft || !nameRight) {
                return 0;
            }
            let nameCompare = nameLeft.localeCompare(nameRight);
            if (nameCompare !== 0) {
                return nameCompare;
            }
            let versionCompare = right.version.localeCompare(left.version);
            if (versionCompare !== 0) {
                return versionCompare
            }
            // TODO should symbolic name be the sorted field?
            let symNameCompare = left.symbolicName.localeCompare(right.symbolicName);
            if (symNameCompare !== 0) {
                return symNameCompare
            }            
            let containingBundleCompare = right.containingBundle.localeCompare(left.containingBundle);
            if (containingBundleCompare !== 0) {
                return containingBundleCompare
            }            
            return 0;
        });
    }
}

function controller($scope, $element, $q, $uibModal, $log, $templateCache, paletteApi, paletteDragAndDropService, iconGenerator, composerOverrides) {
    $scope.pagination = {
        page: 1,
        itemsPerPage: $scope.itemsPerPage || ITEMS_PER_PAGE
    };
    $scope.state = {
        orders: ['name', 'type', 'id'],
        currentOrder: 'name'
    };
    $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.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 => {
            return data;
        }).catch(error => {
            return [];
        }).finally(() => {
            $scope.isLoading = false;
        });
    };
    $scope.onSelectItem = function (item) {
        if (angular.isFunction($scope.onSelect)) {
            $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();
    };
    $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.filterPaletteItems = (items) => items;

    // downstream can override this to insert lines below the header
    $scope.customSubHeadTemplateName = 'composer-palette-empty-sub-head';
    $templateCache.put($scope.customSubHeadTemplateName, '');

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