/*
 * Copyright 2015-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 } from '@angular/core';
import { FnService } from '../../fw/util/fn.service';
import { LogService } from '../../log.service';
import * as gds from './glyphdata.service';
import * as d3 from 'd3';

// constants
const msgGS = 'GlyphService.';
const rg = 'registerGlyphs(): ';
const rgs = 'registerGlyphSet(): ';

/**
 * ONOS GUI -- SVG -- Glyph Service
 */
@Injectable()
export class GlyphService {
    // internal state
    glyphs = d3.map();

    constructor(
        private fs: FnService,
//        private gd: GlyphDataService,
        private log: LogService
    ) {
        this.clear();
        this.init();
        this.log.debug('GlyphService constructed');
    }

    warn(msg: string): void {
        this.log.warn(msgGS + msg);
    }

    addToMap(key, value, vbox, overwrite: boolean, dups) {
        if (!overwrite && this.glyphs.get(key)) {
            dups.push(key);
        } else {
            this.glyphs.set(key, { id: key, vb: vbox, d: value });
        }
    }

    reportDups(dups: string[], which: string): boolean {
        const ok: boolean = (dups.length === 0);
        const msg = 'ID collision: ';

        if (!ok) {
            dups.forEach((id) => {
                this.warn(which + msg + '"' + id + '"');
            });
        }
        return ok;
    }

    reportMissVb(missing: string[], which: string): boolean {
        const ok: boolean = (missing.length === 0);
        const msg = 'Missing viewbox property: ';

        if (!ok) {
            missing.forEach((vbk) => {
                this.warn(which + msg + '"' + vbk + '"');
            });
        }
        return ok;
    }

    clear() {
        // start with a fresh map
        this.glyphs = d3.map();
    }

    init() {
        this.log.info('Registering glyphs');
        this.registerGlyphs(gds.logos);
        this.registerGlyphSet(gds.glyphDataSet);
        this.registerGlyphSet(gds.badgeDataSet);
        this.registerGlyphs(gds.spriteData);
        this.registerGlyphSet(gds.mojoDataSet);
        this.registerGlyphs(gds.extraGlyphs);
    }

    registerGlyphs(data: Map<string, string>, overwrite: boolean = false): boolean {
        const dups: string[] = [];
        const missvb: string[] = [];
        for (const [key, value] of data.entries()) {
            const vbk = '_' + key;
            const vb = data.get(vbk);

            if (key[0] !== '_') {
                if (!vb) {
                    missvb.push(vbk);
                    continue;
                }
                this.addToMap(key, value, vb, overwrite, dups);
            }
        }
        return this.reportDups(dups, rg) && this.reportMissVb(missvb, rg);
    }

    registerGlyphSet(data: Map<string, string>, overwrite: boolean = false): boolean {
        const dups: string[] = [];
        const vb: string = data.get('_viewbox');

        if (!vb) {
            this.warn(rgs + 'no "_viewbox" property found');
            return false;
        }

        for (const [key, value] of data.entries()) {
//        angular.forEach(data, function (value, key) {
            if (key[0] !== '_') {
                this.addToMap(key, value, vb, overwrite, dups);
            }
        }
        return this.reportDups(dups, rgs);
    }

    ids() {
        return this.glyphs.keys();
    }

    glyph(id) {
        return this.glyphs.get(id);
    }

    glyphDefined(id) {
        return this.glyphs.has(id);
    }


    /**
     * Load definitions of a glyph
     *
     * Note: defs should be a D3 selection of a single <defs> element
     */
    loadDefs(defs, glyphIds: string[], noClear: boolean) {
        const list = this.fs.isA(glyphIds) || this.ids();

        if (!noClear) {
            // remove all existing content
            defs.html(null);
        }

        // load up the requested glyphs
        list.forEach((id) => {
            const g = this.glyph(id);
            if (g) {
                if (noClear) {
                    // quick exit if symbol is already present
                    // TODO: check if this should be a continue or break instead
                    if (defs.select('symbol#' + g.id).size() > 0) {
                        return;
                    }
                }
                defs.append('symbol')
                      .attr('id', g.id)
                      .attr('viewBox', g.vb)
                      .append('path')
                      .attr('d', g.d);
            }
        });
    }
}
