/*
 * Copyright 2019-present Open Networking Foundation
 *
 * Licensed 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 {Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core';
import {animate, state, style, transition, trigger} from '@angular/animations';
import {DetailsPanelBaseImpl, FnService, LionService, LogService, WebSocketService} from '../../../../gui2-fw-lib/public_api';
import {Host, Link, LinkType, NodeType, UiElement} from '../../layer/forcesvg/models';
import {Params, Router} from '@angular/router';


interface ButtonAttrs {
    gid: string;
    tt: string;
    path: string;
}

const SHOWDEVICEVIEW: ButtonAttrs = {
    gid: 'deviceTable',
    tt: 'tt_ctl_show_device',
    path: 'device',
};
const SHOWFLOWVIEW: ButtonAttrs = {
    gid: 'flowTable',
    tt: 'title_flows',
    path: 'flow',
};
const SHOWPORTVIEW: ButtonAttrs = {
    gid: 'portTable',
    tt: 'tt_ctl_show_port',
    path: 'port',
};
const SHOWGROUPVIEW: ButtonAttrs = {
    gid: 'groupTable',
    tt: 'tt_ctl_show_group',
    path: 'group',
};
const SHOWMETERVIEW: ButtonAttrs = {
    gid: 'meterTable',
    tt: 'tt_ctl_show_meter',
    path: 'meter',
};
const SHOWPIPECONFVIEW: ButtonAttrs = {
    gid: 'pipeconfTable',
    tt: 'tt_ctl_show_pipeconf',
    path: 'pipeconf',
};
const RELATEDINTENTS: ButtonAttrs = {
    gid: 'm_relatedIntents',
    tt: 'tr_btn_show_related_traffic',
    path: 'relatedIntents',
};
const CREATEHOSTTOHOSTFLOW: ButtonAttrs = {
    gid: 'm_endstation',
    tt: 'tr_btn_create_h2h_flow',
    path: 'create_h2h_flow',
};
const CREATEMULTISOURCEFLOW: ButtonAttrs = {
    gid: 'm_flows',
    tt: 'tr_btn_create_msrc_flow',
    path: 'create_msrc_flow',
};


interface ShowDetails {
    buttons: string[];
    glyphId: string;
    id: string;
    navPath: string;
    propLabels: Object;
    propOrder: string[];
    propValues: Object;
    title: string;
}
/**
 * ONOS GUI -- Topology Details Panel.
 * Displays details of selected device. When no device is selected the panel slides
 * off to the side and disappears
 *
 * This Panel is a child of the Topology component and it gets the 'selectedNodes'
 * from there as an input component. See TopologyComponent.nodeSelected()
 * The topology component gets these by listening to events from ForceSvgComponent
 * which gets them in turn from Device, Host, SubRegion and Link components. This
 * is so that each component respects the hierarchy
 */
@Component({
    selector: 'onos-details',
    templateUrl: './details.component.html',
    styleUrls: [
        './details.component.css', './details.theme.css',
        '../../topology.common.css',
        '../../../../gui2-fw-lib/lib/widget/panel.css',
        '../../../../gui2-fw-lib/lib/widget/panel-theme.css'
    ],
    animations: [
        trigger('detailsPanelState', [
            state('true', style({
                transform: 'translateX(0%)',
                opacity: '1.0'
            })),
            state('false', style({
                transform: 'translateX(100%)',
                opacity: '0'
            })),
            transition('0 => 1', animate('100ms ease-in')),
            transition('1 => 0', animate('100ms ease-out'))
        ])
    ]
})
export class DetailsComponent extends DetailsPanelBaseImpl implements OnInit, OnDestroy, OnChanges {
    @Input() selectedNodes: UiElement[] = []; // Populated when user selects node or link
    @Input() on: boolean = false; // Override the parent class attribute

    // deferred localization strings
    lionFnTopo; // Function
    lionFnFlow; // Function for flow bundle
    showDetails: ShowDetails; // Will be populated on callback. Cleared if nothing is selected

    constructor(
        protected fs: FnService,
        protected log: LogService,
        protected router: Router,
        protected wss: WebSocketService,
        private lion: LionService
    ) {
        super(fs, log, wss, 'topo');

        if (this.lion.ubercache.length === 0) {
            this.lionFnTopo = this.dummyLion;
            this.lionFnFlow = this.dummyLion;
            this.lion.loadCbs.set('detailscore', () => this.doLion());
        } else {
            this.doLion();
        }

        this.log.debug('Topo DetailsComponent constructed');
    }

    /**
     * When the component is initializing set up the handler for callbacks of
     * ShowDetails from the WSS. Set the variable showDetails when ever a callback
     * is made
     */
    ngOnInit(): void {
        this.wss.bindHandlers(new Map<string, (data) => void>([
            ['showDetails', (data) => {
                    this.showDetails = data;
                    // this.log.debug('showDetails received', data);
                }
            ]
        ]));
        this.log.debug('Topo DetailsComponent initialized');
    }

    /**
     * When the component is being unloaded then unbind the WSS handler.
     */
    ngOnDestroy(): void {
        this.wss.unbindHandlers(['showDetails']);
        this.log.debug('Topo DetailsComponent destroyed');
    }

    /**
     * If changes are detected on the Input param selectedNode, call on WSS sendEvent
     * and expect ShowDetails to be updated from data sent back from server.
     *
     * Note the difference in call to the WSS with requestDetails between a node
     * and a link - the handling is done in TopologyViewMessageHandler#RequestDetails.process()
     *
     * When multiple items are selected fabricate the ShowDetails here, and
     * present buttons that allow custom actions
     *
     * The WSS will call back asynchronously (see fn in ngOnInit())
     *
     * @param changes Simple Changes set of updates
     */
    ngOnChanges(changes: SimpleChanges): void {
        if (changes['selectedNodes']) {
            this.selectedNodes = changes['selectedNodes'].currentValue;
            let type: any;
            if (this.selectedNodes.length === 0) {
                // Selection has been cleared
                this.showDetails = <ShowDetails>{};
                return;
            } else if (this.selectedNodes.length > 1) {
                // Don't send message to WSS just form dialog here
                const propOrder: string[] = [];
                const propValues: Object = {};
                const propLabels: Object = {};
                let numHosts: number = 0;
                for (let i = 0; i < this.selectedNodes.length; i++) {
                    propOrder.push(i.toString());
                    propLabels[i.toString()] = i.toString();
                    propValues[i.toString()] = this.selectedNodes[i].id;
                    if (this.selectedNodes[i].hasOwnProperty('nodeType') &&
                        (<Host>this.selectedNodes[i]).nodeType === NodeType.HOST) {
                        numHosts++;
                    } else {
                        numHosts = -128; // Negate the whole thing so other buttons will not be shown
                    }
                }
                const buttons: string[] = [];
                if (numHosts === 2) {
                    buttons.push('createHostToHostFlow');
                } else if (numHosts > 2) {
                    buttons.push('createMultiSourceFlow');
                }
                buttons.push('relatedIntents');

                this.showDetails = <ShowDetails>{
                    buttons: buttons,
                    glyphId: undefined,
                    id: 'multiple',
                    navPath: undefined,
                    propLabels: propLabels,
                    propOrder: propOrder,
                    propValues: propValues,
                    title: this.lionFnTopo('title_selected_items')
                };
                this.log.debug('Details panel generated from multiple devices', this.showDetails);
                return;
            }

            // If only one thing has been selected then request details of that from the server
            const selectedNode = this.selectedNodes[0];
            if (selectedNode.hasOwnProperty('nodeType')) { // For Device, Host, SubRegion
                type = (<Host>selectedNode).nodeType;
                this.wss.sendEvent('requestDetails', {
                    id: selectedNode.id,
                    class: type,
                });
            } else if (selectedNode.hasOwnProperty('type')) { // Must be link
                const link: Link = <Link>selectedNode;
                if (<LinkType><unknown>LinkType[link.type] === LinkType.UiEdgeLink) { // Number based enum
                    this.wss.sendEvent('requestDetails', {
                        key: link.id,
                        class: 'link',
                        sourceId: link.epA,
                        targetId: Link.deviceNameFromEp(link.epB),
                        targetPort: link.portB,
                        isEdgeLink: true
                    });
                } else {
                    this.wss.sendEvent('requestDetails', {
                        key: link.id,
                        class: 'link',
                        sourceId: Link.deviceNameFromEp(link.epA),
                        sourcePort: link.portA,
                        targetId: Link.deviceNameFromEp(link.epB),
                        targetPort: link.portB,
                        isEdgeLink: false
                    });
                }
            } else {
                this.log.warn('Unexpected type for selected element', selectedNode);
            }
        }
    }

    /**
     * Table of core button attributes to return per button icon
     * @param btnName The name of the button
     * @returns A structure with the button attributes
     */
    buttonAttribs(btnName: string): ButtonAttrs {
        switch (btnName) {
            case 'showDeviceView':
                return SHOWDEVICEVIEW;
            case 'showFlowView':
                return SHOWFLOWVIEW;
            case 'showPortView':
                return SHOWPORTVIEW;
            case 'showGroupView':
                return SHOWGROUPVIEW;
            case 'showMeterView':
                return SHOWMETERVIEW;
            case 'showPipeConfView':
                return SHOWPIPECONFVIEW;
            case 'relatedIntents':
                return RELATEDINTENTS;
            case 'createHostToHostFlow':
                return CREATEHOSTTOHOSTFLOW;
            case 'createMultiSourceFlow':
                return CREATEMULTISOURCEFLOW;
            default:
                return <ButtonAttrs>{
                    gid: btnName,
                    path: btnName
                };
        }
    }

    /**
     * Navigate using Angular Routing. Combines the parameters to generate a relative URL
     * e.g. if params are 'meter', 'device' and 'null:0000000000001' then the
     * navigation URL will become "http://localhost:4200/#/meter?devId=null:0000000000000002"
     *
     * When multiple hosts are selected other actions have to be accommodated
     *
     * @param path The path to navigate to
     * @param navPath The parameter name to use
     * @param selId the parameter value to use
     */
    navto(path: string): void {
        this.log.debug('navigate to', path, 'for',
            this.showDetails.navPath, '=', this.showDetails.id);

        const ids: string[] = [];
        Object.values(this.showDetails.propValues).forEach((v) => ids.push(v));
        if (path === 'relatedIntents' && this.showDetails.id === 'multiple') {
            this.wss.sendEvent('topo2RequestRelatedIntents', {
                'ids': ids,
                'hover': ''
            });

        } else if (path === 'create_h2h_flow' && this.showDetails.id === 'multiple') {
            this.wss.sendEvent('topo2AddHostIntent', {
                'one': ids[0],
                'two': ids[1],
                'ids': ids
            });

        } else if (path === 'create_msrc_flow' && this.showDetails.id === 'multiple') {
            // Should only happen when there are 3 or more ids
            this.wss.sendEvent('topo2AddMultiSourceIntent', {
                'src': ids.slice(0, ids.length - 1),
                'dst': ids[ids.length - 1],
                'ids': ids
            });

        } else if (this.showDetails.id) {
            let navPath = this.showDetails.navPath;
            if (navPath === 'device') {
                navPath = 'devId';
            }
            const queryPar: Params = {};
            queryPar[navPath] = this.showDetails.id;
            this.router.navigate([path], { queryParams: queryPar });
        }
    }

    /**
     * Read the LION bundle for Details panel and set up the lionFn
     */
    doLion() {
        this.lionFnTopo = this.lion.bundle('core.view.Topo');
        this.lionFnFlow = this.lion.bundle('core.view.Flow');
    }

}
