/*
 * Copyright 2014-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 { Injectable, Inject } from '@angular/core';
import { ActivatedRoute, Router} from '@angular/router';
import { LogService } from '../../log.service';

// Angular>=2 workaround for missing definition
declare const InstallTrigger: any;

const matcher = /<\/?([a-zA-Z0-9]+)*(.*?)\/?>/igm;
const whitelist: string[] = ['b', 'i', 'p', 'em', 'strong', 'br'];
const evillist: string[] = ['script', 'style', 'iframe'];

/**
 * Used with the Window size function;
 **/
export interface WindowSize {
    width: number;
    height: number;
}

/**
 * For the sanitize() and analyze() functions
 */
export interface Match {
    full: string;
    name: string;
}

// TODO Move all this trie stuff to its own class
// Angular>=2 Tightened up on types to avoid compiler errors
interface TrieC {
    p: any;
    s: string[];
}
// trie operation
function _trieOp(op: string, trie, word: string, data) {
    const p = trie;
    const w: string = word.toUpperCase();
    const s: Array<string> = w.split('');
    let c: TrieC = { p: p, s: s };
    let t = [];
    let  x = 0;
    const f1 = op === '+' ? add : probe;
    const f2 = op === '+' ? insert : remove;

    function add(cAdded): TrieC {
        const q = cAdded.s.shift();
        let np = cAdded.p[q];

        if (!np) {
            cAdded.p[q] = {};
            np = cAdded.p[q];
            x = 1;
        }
        return { p: np, s: cAdded.s };
    }

    function probe(cProbed): TrieC {
        const q = cProbed.s.shift();
        const k: number = Object.keys(cProbed.p).length;
        const np = cProbed.p[q];

        t.push({ q: q, k: k, p: cProbed.p });
        if (!np) {
            t = [];
            return { p: [], s: [] };
        }
        return { p: np, s: cProbed.s };
    }

    function insert() {
        c.p._data = data;
        return x ? 'added' : 'updated';
    }

    function remove() {
        if (t.length) {
            t = t.reverse();
            while (t.length) {
                const d = t.shift();
                delete d.p[d.q];
                if (d.k > 1) {
                    t = [];
                }
            }
            return 'removed';
        }
        return 'absent';
    }

    while (c.s.length) {
        c = f1(c);
    }
    return f2();
}

// add word to trie (word will be converted to uppercase)
// data associated with the word
// returns 'added' or 'updated'
function addToTrie(trie, word, data) {
    return _trieOp('+', trie, word, data);
}

// remove word from trie (word will be converted to uppercase)
// returns 'removed' or 'absent'
// Angular>=2 added in quotes for data. error TS2554: Expected 4 arguments, but got 3.
function removeFromTrie(trie, word) {
    return _trieOp('-', trie, word, '');
}

// lookup word (converted to uppercase) in trie
// returns:
//    undefined if the word is not in the trie
//    -1 for a partial match (word is a prefix to an existing word)
//    data for the word for an exact match
function trieLookup(trie, word) {
    const s = word.toUpperCase().split('');
    let p = trie;
    let n;

    while (s.length) {
        n = s.shift();
        p = p[n];
        if (!p) {
            return undefined;
        }
    }
    if (p._data) {
        return p._data;
    }
    return -1;
}


/**
 * ONOS GUI -- Util -- General Purpose Functions
 */
@Injectable()
export class FnService {
    // internal state
    private debugFlags = new Map<string, boolean>([
//        [ "LoadingService", true ]
    ]);

    constructor(
        private route: ActivatedRoute,
        private log: LogService,
        @Inject(Window) private w: Window
    ) {
        this.route.queryParams.subscribe(params => {
            const debugparam: string = params['debug'];
            log.debug('Param:', debugparam);
            this.parseDebugFlags(debugparam);
        });
        log.debug('FnService constructed');
    }

    /**
     * Test if an argument is a function
     *
     * Note: the need for this would go away if all functions
     * were strongly typed
     */
    isF(f: any): any {
        return typeof f === 'function' ? f : null;
    }

    /**
     * Test if an argument is an array
     *
     * Note: the need for this would go away if all arrays
     * were strongly typed
     */
    isA(a: any): any {
    // NOTE: Array.isArray() is part of EMCAScript 5.1
        return Array.isArray(a) ? a : null;
    }

    /**
     * Test if an argument is a string
     *
     * Note: the need for this would go away if all strings
     * were strongly typed
     */
    isS(s: any): string {
        return typeof s === 'string' ? s : null;
    }

    /**
     * Test if an argument is an object
     *
     * Note: the need for this would go away if all objects
     * were strongly typed
     */
    isO(o: any): Object {
        return (o && typeof o === 'object' && o.constructor === Object) ? o : null;
    }

    /**
     * Test that an array contains an object
     */
    contains(a: any[], x: any): boolean {
        return this.isA(a) && a.indexOf(x) > -1;
    }

    /**
     * Returns width and height of window inner dimensions.
     * offH, offW : offset width/height are subtracted, if present
     */
    windowSize(offH: number = 0, offW: number = 0): WindowSize {
        return {
            height: this.w.innerHeight - offH,
            width: this.w.innerWidth - offW
        };
    }

    /**
     * Returns true if all names in the array are defined as functions
     * on the given api object; false otherwise.
     * Also returns false if there are properties on the api that are NOT
     * listed in the array of names.
     *
     * This gets extra complicated when the api Object is an
     * Angular service - while the functions can be retrieved
     * by an indexed get, the ownProperties does not show the
     * functions of the class. We have to dive in to the prototypes
     * properties to get these - and even then we have to filter
     * out the constructor and any member variables
     */
    areFunctions(api: Object, fnNames: string[]): boolean {
        const fnLookup: Map<string, boolean> = new Map();
        let extraFound: boolean = false;

        if (!this.isA(fnNames)) {
            return false;
        }

        const n: number = fnNames.length;
        let i: number;
        let name: string;

        for (i = 0; i < n; i++) {
            name = fnNames[i];
            if (!this.isF(api[name])) {
                return false;
            }
            fnLookup.set(name, true);
        }

        // check for properties on the API that are not listed in the array,
        const keys = Object.getOwnPropertyNames(api);
        if (keys.length === 0) {
            return true;
        }
        // If the api is a class it will have a name,
        //  else it will just be called 'Object'
        const apiObjectName: string = api.constructor.name;
        if (apiObjectName === 'Object') {
            Object.keys(api).forEach((key) => {
                if (!fnLookup.get(key)) {
                    extraFound = true;
                }
            });
        } else { // It is a class, so its functions will be in the child (prototype)
            const pObj: Object = Object.getPrototypeOf(api);
            for ( const key in Object.getOwnPropertyDescriptors(pObj) ) {
                if (key === 'constructor') { // Filter out constructor
                    continue;
                }
                const value = Object.getOwnPropertyDescriptor(pObj, key);
                // Only compare functions. Look for any not given in the map
                if (this.isF(value.value) && !fnLookup.get(key)) {
                    extraFound = true;
                }
            }
        }
        return !extraFound;
    }

    /**
     * Returns true if all names in the array are defined as functions
     * on the given api object; false otherwise. This is a non-strict version
     * that does not care about other properties on the api.
     */
    areFunctionsNonStrict(api, fnNames): boolean {
        if (!this.isA(fnNames)) {
            return false;
        }
        const n = fnNames.length;
        let i;
        let name;

        for (i = 0; i < n; i++) {
            name = fnNames[i];
            if (!this.isF(api[name])) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns true if current browser determined to be a mobile device
     */
    isMobile() {
        const ua = this.w.navigator.userAgent;
        const patt = /iPhone|iPod|iPad|Silk|Android|BlackBerry|Opera Mini|IEMobile/;
        return patt.test(ua);
    }

    /**
     * Returns true if the current browser determined to be Chrome
     */
    isChrome() {
        const isChromium = (this.w as any).chrome;
        const vendorName = this.w.navigator.vendor;

        const isOpera = this.w.navigator.userAgent.indexOf('OPR') > -1;
        return (isChromium !== null &&
        isChromium !== undefined &&
        vendorName === 'Google Inc.' &&
        isOpera === false);
    }

    isChromeHeadless() {
        const vendorName = this.w.navigator.vendor;
        const headlessChrome = this.w.navigator.userAgent.indexOf('HeadlessChrome') > -1;

        return (vendorName === 'Google Inc.' && headlessChrome === true);
    }

    /**
     * Returns true if the current browser determined to be Safari
     */
    isSafari() {
        return (this.w.navigator.userAgent.indexOf('Safari') !== -1 &&
        this.w.navigator.userAgent.indexOf('Chrome') === -1);
    }

    /**
     * Returns true if the current browser determined to be Firefox
     */
    isFirefox() {
        return typeof InstallTrigger !== 'undefined';
    }

    /**
     * search through an array of objects, looking for the one with the
     * tagged property matching the given key. tag defaults to 'id'.
     * returns the index of the matching object, or -1 for no match.
     */
    find(key: string, array: Object[], tag: string = 'id'): number {
        let idx: number;
        const n: number = array.length;

        for (idx = 0 ; idx < n; idx++) {
            const d: Object = array[idx];
            if (d[tag] === key) {
                return idx;
            }
        }
        return -1;
    }

    /**
     * search through array to find (the first occurrence of) item,
     * returning its index if found; otherwise returning -1.
     */
    inArray(item: any, array: any[]): number {
        if (this.isA(array)) {
            for (let i = 0; i < array.length; i++) {
                if (array[i] === item) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * remove (the first occurrence of) the specified item from the given
     * array, if any. Return true if the removal was made; false otherwise.
     */
    removeFromArray(item: any, array: any[]): boolean {
        const i: number = this.inArray(item, array);
        if (i >= 0) {
            array.splice(i, 1);
            return true;
        }
        return false;
    }

    /**
     * return true if the object is empty, return false otherwise
     */
    isEmptyObject(obj: Object): boolean {
        for (const key in obj) {
            if (true) { return false; }
        }
        return true;
    }

    /**
     * Return the given string with the first character capitalized.
     */
    cap(s: string): string {
        return s ? s[0].toUpperCase() + s.slice(1).toLowerCase() : s;
    }

    /**
     * return the parameter without a px suffix
     */
    noPx(num: string): number {
        return Number(num.replace(/px$/, ''));
    }

    /**
     * return an element's given style property without px suffix
     */
    noPxStyle(elem: any, prop: string): number {
        return Number(elem.style(prop).replace(/px$/, ''));
    }

    /**
     * Return true if a str ends with suffix
     */
    endsWith(str: string, suffix: string) {
        return str.indexOf(suffix, str.length - suffix.length) !== -1;
    }

    /**
     * output debug message to console, if debug tag set...
     * e.g. fs.debug('mytag', arg1, arg2, ...)
     */
    debug(tag, ...args) {
        if (this.debugFlags.get(tag)) {
            this.log.debug(tag, args.join());
        }
    }

    private parseDebugFlags(dbgstr: string): void {
        const bits = dbgstr ? dbgstr.split(',') : [];
        bits.forEach((key) => {
            this.debugFlags.set(key, true);
        });
        this.log.debug('Debug flags:', dbgstr);
    }

    /**
      * Return true if the given debug flag was specified in the query params
      */
    debugOn(tag: string): boolean {
        return this.debugFlags.get(tag);
    }



    // -----------------------------------------------------------------
    // The next section deals with sanitizing external strings destined
    // to be loaded via a .html() function call.
    //
    // See definition of matcher, evillist and whitelist at the top of this file

    /*
     * Returns true if the tag is in the evil list, (and is not an end-tag)
     */
    inEvilList(tag: any): boolean {
        return (evillist.indexOf(tag.name) !== -1 && tag.full.indexOf('/') === -1);
    }

    /*
     * Returns an array of Matches of matcher in html
     */
    analyze(html: string): Match[] {
        const matches: Match[] = [];
        let match;

        // extract all tags
        while ((match = matcher.exec(html)) !== null) {
            matches.push({
                full: match[0],
                name: match[1],
                // NOTE: ignoring attributes {match[2].split(' ')} for now
            });
        }

        return matches;
    }

    /*
     * Returns a cleaned version of html
     */
    sanitize(html: string): string {
        const matches: Match[] = this.analyze(html);

        // completely obliterate evil tags and their contents...
        evillist.forEach((tag) => {
            const re = new RegExp('<' + tag + '(.*?)>(.*?[\r\n])*?(.*?)(.*?[\r\n])*?<\/' + tag + '>', 'gim');
            html = html.replace(re, '');
        });

        // filter out all but white-listed tags and end-tags
        matches.forEach((tag) => {
            if (whitelist.indexOf(tag.name) === -1) {
                html = html.replace(tag.full, '');
                if (this.inEvilList(tag)) {
                    this.log.warn('Unsanitary HTML input -- ' +
                        tag.full + ' detected!');
                }
            }
        });

        // TODO: consider encoding HTML entities, e.g. '&' -> '&amp;'

        return html;
    }

}
