/*
 * 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 brIconGenerator from 'brooklyn-ui-utils/icon-generator/icon-generator';
import brooklynCatalogApi from 'brooklyn-ui-utils/providers/catalog-api.provider';
import brooklynTypeItem from '../../components/type-item/index';
import brUtils from 'brooklyn-ui-utils/utils/general';
import template from './catalog.template.html';
import {analyzeDescription} from 'brooklyn-ui-utils/md-helper';
import {HIDE_INTERSTITIAL_SPINNER_EVENT} from 'brooklyn-ui-utils/interstitial-spinner/interstitial-spinner';

const MODULE_NAME = 'catalog.state';

angular.module(MODULE_NAME, [brIconGenerator, brooklynCatalogApi, brooklynTypeItem, brUtils])
    .config(['$stateProvider', catalogStateConfig])
    .filter('bundleName', ['$sce', bundleNameFilter])
    .filter('bundleDescription', ['$sce', bundleDescriptionFilter])
    .filter('bundleHighlights', ['$sce', bundleHighlightsFilter])
    .filter('bundleTypeFilter', ['$sce', bundleTypeFilter]);

export default MODULE_NAME;

export const catalogState = {
    name: 'catalog',
    url: '/',
    template: template,
    controller: ['$scope', '$rootScope', 'catalogApi', 'brUtilsGeneral', catalogController],
    controllerAs: 'ctrl'
};

export function catalogStateConfig($stateProvider) {
    $stateProvider.state(catalogState);
}

export function catalogController($scope, $rootScope, catalogApi, brUtilsGeneral) {
    const orderBysBundles = [{
        id: 'name',
        label: 'Name'
    }, {
        id: '-version',
        label: 'Version'
    }, {
        id: '-types',
        label: 'Most types'
    }, {
        id: 'types',
        label: 'Least types'
    }];
    const orderBysTypes = [{
        id: 'displayName',
        label: 'Display name'
    }, {
        id: 'id',
        label: 'Type name'
    }, {
        id: '-version',
        label: 'Version'
    }, {
        id: 'supertypes',
        label: 'Supertype'
    }, {
        id: 'containingBundle',
        label: 'Bundle'
    }];

    const savedOrderByKey = 'catalog-order-by';

    const savedOrderBy = localStorage && localStorage.getItem(savedOrderByKey) !== null ?
        JSON.parse(localStorage.getItem(savedOrderByKey))
        : {
            orderBy: 'bundles',
            sortBy: 0
        }

    $scope.pagination = {
        page: 1, // not used
        itemsPerPage: 20  // used as an absolute limit
    };
    $scope.config = {
        orderBy: savedOrderBy.orderBy === 'bundles' ? orderBysBundles : orderBysTypes
    };
    $scope.state = {
        view: savedOrderBy.orderBy,
        versions: [],
        orderBy: $scope.config.orderBy.length > savedOrderBy.sortBy ? $scope.config.orderBy[savedOrderBy.sortBy] : 0,
        search: {}
    };

    $scope.$watch('state.view', (newView, oldView) => {
        if (newView && oldView && !angular.equals(newView, oldView)) {
            $scope.config.orderBy = newView === 'types' ? orderBysTypes : orderBysBundles;
            $scope.state.orderBy = $scope.config.orderBy[0]
            savedOrderBy.orderBy = newView;
            savedOrderBy.sortBy = 0;
            if (localStorage) {
                localStorage.setItem(savedOrderByKey, JSON.stringify(savedOrderBy));
            }
        }
    });

    $scope.$watch('state.orderBy', (newOrderBy, oldOrderBy) => {
        if(newOrderBy && oldOrderBy && !angular.equals(newOrderBy, oldOrderBy)) {
            savedOrderBy.sortBy = $scope.config.orderBy.indexOf(newOrderBy);
            if (localStorage) {
                localStorage.setItem(savedOrderByKey, JSON.stringify(savedOrderBy));
            }
        }
    });

    $scope.clearSearchFilters = () => {
        $scope.state.search = {};
        $scope.state.orderBy = orderBysBundles[0];
    };

    $scope.isNonEmpty = (o) => {
        return brUtilsGeneral.isNonEmpty(o);
    };

    $scope.launchCatalogUploader = ()=> {
        $rootScope.$broadcast('open-catalog-uploader');
    };

    catalogApi.getBundles({params: {detail: true}}).then(data => {
        $scope.$emit(HIDE_INTERSTITIAL_SPINNER_EVENT);

        processBundles(data);
    });

    function processBundles(bundles) {
        $scope.bundles = bundles;

        $scope.versions = bundles.reduce((versions, bundle) => {
            if (!versions.hasOwnProperty(bundle.symbolicName)) {
                versions[bundle.symbolicName] = [];
            }
            versions[bundle.symbolicName].push(bundle.version);
            return versions;
        }, {});
        $scope.config.versions = Array.from(Object.values($scope.versions).reduce((set, versions) => {
            versions.forEach(version => set.add(version));
            return set;
        }, new Set()));

        $scope.types = bundles.reduce((types, bundle) => {
            let typesInBundle = angular.copy(bundle.types).map(t => {
                // record the bundle
                t.bundle = {
                    symbolicName: bundle.symbolicName,
                    version: bundle.version,
                };
                
                // tidy up display so that things labelled [DEPRECATED] don't have that ugly name
                // (since we highlight deprecated things, and particularly bad since [ appears first alphabetically!)
                // [as in bundle.state.js]
                if (t.deprecated && t.displayName.match(/^[^\w]*deprecated[^\w]*/i)) {
                    t.displayName = t.displayName.replace(/^[^\w]*deprecated[^\w]*/i, '');
                }
                
                return t;
            });
            return types.concat(typesInBundle);
        }, []);
    }
}

export function bundleNameFilter() {
    return function(input) {
        if (!input) {
            return;
        }
        // we could give better names to these unhelpful bundle names;
        // but actually doing so currently is jarring as all the other bundle names
        // are in symbolic name format and this is in display name format;
        // if we had nice bundle display names it would make much more sense to do this:
        // (reenable when we have display names for bundles)
//        if (input.symbolicName && input.symbolicName.startsWith('brooklyn-catalog-bom')) {
//            return 'Unnamed bundle';
//        }
        return input.symbolicName;
    }
}

export function bundleDescriptionFilter() {
    return function(input) {
        if (!input) {
            return;
        }
        if (input.description) {
            // bundles don't have description yet so this is moot, but when they do this will be nice - or better use the md-if-multiline widget from mdHelper
            return analyzeDescription(input).oneline;
        }

        let alwaysGenerateDefaultDescription = true;
        if (alwaysGenerateDefaultDescription || (input.symbolicName && input.symbolicName.startsWith('brooklyn-catalog-bom'))) {
            // useful in anonymous case because the name gives no clue as to the title;
            // useful in other cases too, even if redundant, but as a flag above in case we don't want to do that
            if (angular.isArray(input.types) && input.types.length > 0) {
                let displayedTypes = input.types.slice(0, input.types.length > 3 ? 2 : input.types.length);
                let description = `Composed of ${displayedTypes.map(type => type.displayName || type.symbolicName).join(', ')}`;
                if (input.types.length > displayedTypes.length) {
                    description += ` and ${input.types.length - displayedTypes.length} more items`;
                }
                return description;
            } else {
                return "This is likely a support bundle."
            }
        }
    }
}

export function bundleHighlightsFilter($sce) {
    return function(input) {
        let highlights = [];

        if (input && input.types) {
            let entities = input.types.filter(type => type.supertypes.includes('org.apache.brooklyn.api.entity.Entity')).length;
            let policies = input.types.filter(type => type.supertypes.includes('org.apache.brooklyn.api.policy.Policy')).length;
            let enrichers = input.types.filter(type => type.supertypes.includes('org.apache.brooklyn.api.sensor.Enricher')).length;

            if (entities > 0) {
                highlights.push({
                    label: (entities==1 ? 'entity' : 'entities'),
                    count: entities
                });
            }
            if (policies > 0) {
                highlights.push({
                    label: (policies==1 ? 'policy' : 'policies'),
                    count: policies
                });
            }
            if (enrichers > 0) {
                highlights.push({
                    label: (enrichers==1 ? 'enricher' : 'enrichers'),
                    count: enrichers
                });
            }
        }

        return $sce.trustAsHtml(highlights.map(highlight => {
            return `<span class="highlight-count">${highlight.count}</span>&nbsp;<span class="highlight-label">${highlight.label}</span>`
        }).join('&nbsp;'));
    };
}

export function bundleTypeFilter() {
    return function(input, superType) {
        return input && input.filter(type => type.supertypes.includes(superType));
    }
}
