/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * 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.
 */

/*
 ONOS GUI -- Topo View -- Topo Model Service - Unit Tests
 */
describe('factory: view/topo/topoModel.js', function() {
    var $log, fs, rnd, tms;

    // stop random numbers from being quite so random
    var mockRandom = {
        // mock spread returns s + 1
        spread: function (s) {
            return s + 1;
        },
        // mock random dimension returns d / 2 - 1
        randDim: function (d) {
            return d/2 - 1;
        },
        mock: 'yup'
    };

    // to mock out the [lng,lat] <=> [x,y] transformations, we will
    // add/subtract 2000, 3000 respectively:
    //   lng:2005 === x:5,   lat:3004 === y:4

    var mockProjection = function (lnglat) {
        return [lnglat[0] - 2000, lnglat[1] - 3000];
    };

    mockProjection.invert = function (xy) {
        return [xy[0] + 2000, xy[1] + 3000];
    };

    // our test devices and hosts:
    var dev1 = {
            'class': 'device',
            id: 'dev1',
            x: 17,
            y: 27,
            online: true
        },
        dev2 = {
            'class': 'device',
            id: 'dev2',
            x: 18,
            y: 28,
            online: true
        },
        host1 = {
            'class': 'host',
            id: 'host1',
            x: 23,
            y: 33,
            cp: {
                device: 'dev1',
                port: 7
            },
            ingress: 'dev1/7-host1'
        },
        host2 = {
            'class': 'host',
            id: 'host2',
            x: 24,
            y: 34,
            cp: {
                device: 'dev0',
                port: 0
            },
            ingress: 'dev0/0-host2'
        };


    // our test api
    var api = {
        projection: function () { return mockProjection; },
        network: {
            nodes: [dev1, dev2, host1, host2],
            links: [],
            lookup: {dev1: dev1, dev2: dev2, host1: host1, host2: host2},
            revLinkToKey: {}
        },
        restyleLinkElement: function () {},
        removeLinkElement: function () {}
    };

    // our test dimensions and well known locations..
    var dim = [20, 40],
        randLoc = [9, 19],          // random location using randDim(): d/2-1
        randHostLoc = [40, 50],     // host "near" random location
                                    //  given that 'nearDist' = 15
                                    //  and spread(15) = 16
                                    //  9 + 15 + 16 = 40; 19 + 15 + 16 = 50
        nearDev1 = [48,58],         // [17+15+16, 27+15+16]
        dev1Loc = [17,27],
        dev2Loc = [18,28],
        host1Loc = [23,33],
        host2Loc = [24,34];

    // implement some custom matchers...
    beforeEach(function () {
        jasmine.addMatchers({
            toBePositionedAt: function () {
                return {
                    compare: function (actual, xy) {
                        var result = {},
                            actCoord = [actual.x, actual.y];

                        result.pass = (actual.x === xy[0]) && (actual.y === xy[1]);

                        if (result.pass) {
                            // for negation with ".not"
                            result.message = 'Expected [' + actCoord +
                            '] NOT to be positioned at [' + xy + ']';
                        } else {
                            result.message = 'Expected [' + actCoord +
                            '] to be positioned at [' + xy + ']';
                        }
                        return result;
                    }
                }
            },
            toHaveEndPoints: function () {
                return {
                    compare: function (actual, xy1, xy2) {
                        var result = {};

                        result.pass = (actual.source.x === xy1[0]) &&
                                      (actual.source.y === xy1[1]) &&
                                      (actual.target.x === xy2[0]) &&
                                      (actual.target.y === xy2[1]);

                        if (result.pass) {
                            // for negation with ".not"
                            result.message = 'Expected ' + actual +
                            ' NOT to have endpoints [' + xy1 + ']-[' + xy2 + ']';
                        } else {
                            result.message = 'Expected ' + actual +
                            ' to have endpoints [' + xy1 + ']-[' + xy2 + ']';
                        }
                        return result;
                    }
                }
            },
            toBeFixed: function () {
                return {
                    compare: function (actual) {
                        var result = {
                            pass: actual.fixed
                        };
                        if (result.pass) {
                            result.message = 'Expected ' + actual +
                            ' NOT to be fixed!';
                        } else {
                            result.message = 'Expected ' + actual +
                            ' to be fixed!';
                        }
                        return result;
                    }
                }
            }
        });
    });

    beforeEach(module('ovTopo', 'onosUtil', 'onosNav', 'onosLayer', 'onosWidget', 'onosMast'));

    beforeEach(function () {
        module(function ($provide) {
            $provide.value('RandomService', mockRandom);
        });
    });

    beforeEach(inject(function (_$log_, FnService, RandomService, TopoModelService) {
        $log = _$log_;
        fs = FnService;
        rnd = RandomService;
        tms = TopoModelService;
        tms.initModel(api, dim);
    }));


    it('should install the mock random service', function () {
        expect(rnd.mock).toBe('yup');
        expect(rnd.spread(4)).toBe(5);
        expect(rnd.randDim(8)).toBe(3);
    });

    it('should install the mock projection', function () {
        expect(tms.coordFromLngLat({lng: 2005, lat: 3004})).toEqual([5,4]);
        expect(tms.lngLatFromCoord([5,4])).toEqual([2005,3004]);
    });

    it('should define TopoModelService', function () {
        expect(tms).toBeDefined();
    });

    xit('should define api functions', function () {
        expect(fs.areFunctions(tms, [
            'initModel', 'newDim', 'destroyModel',
            'positionNode', 'createDeviceNode', 'createHostNode',
            'createHostLink', 'createLink',
            'coordFromLngLat', 'lngLatFromCoord',
            'findLink', 'findLinkById', 'findDevices',
            'findAttachedHosts', 'findAttachedLinks', 'findBadLinks'
        ])).toBeTruthy();
    });

    // === unit tests for positionNode()

    it('should position a node using meta x/y', function () {
        var node = {
            metaUi: { x:37, y:48 }
        };
        tms.positionNode(node);
        expect(node).toBePositionedAt([37,48]);
        expect(node).toBeFixed();
    });

    it('should position a node by translating lng/lat', function () {
        var node = {
            location: {
                type: 'lnglat',
                lng: 2008,
                lat: 3009
            }
        };
        tms.positionNode(node);
        expect(node).toBePositionedAt([8,9]);
        expect(node).toBeFixed();
    });

    it('should position a device with no location randomly', function () {
        var node = { 'class': 'device' };
        tms.positionNode(node);
        expect(node).toBePositionedAt(randLoc);
        expect(node).not.toBeFixed();
    });

    it('should position a device randomly even if x/y set', function () {
        var node = { 'class': 'device', x: 1, y: 2 };
        tms.positionNode(node);
        expect(node).toBePositionedAt(randLoc);
        expect(node).not.toBeFixed();
    });

    it('should NOT reposition a device randomly on update', function () {
        var node = { 'class': 'device', x: 1, y: 2 };
        tms.positionNode(node, true);
        expect(node).toBePositionedAt([1,2]);
        expect(node).not.toBeFixed();
    });

    it('should position a host close to its device', function () {
        var node = { 'class': 'host', cp: { device: 'dev1' } };
        tms.positionNode(node);

        // note: nearDist is 15; spread(15) adds 16; dev1 at [17,27]

        expect(node).toBePositionedAt(nearDev1);
        expect(node).not.toBeFixed();
    });

    it('should randomize host with no assoc device', function () {
        var node = { 'class': 'host', cp: { device: 'dev0' } };
        tms.positionNode(node);

        // note: no device gives 'rand loc' [9,19]
        //       nearDist is 15; spread(15) adds 16

        expect(node).toBePositionedAt(randHostLoc);
        expect(node).not.toBeFixed();
    });

    // === unit tests for createDeviceNode()

    it('should create a basic device node', function () {
        var node = tms.createDeviceNode({ id: 'foo' });
        expect(node).toBePositionedAt(randLoc);
        expect(node).not.toBeFixed();
        expect(node.class).toEqual('device');
        expect(node.svgClass).toEqual('node device');
        expect(node.id).toEqual('foo');
    });

    it('should create device node with type', function () {
        var node = tms.createDeviceNode({ id: 'foo', type: 'cool' });
        expect(node).toBePositionedAt(randLoc);
        expect(node).not.toBeFixed();
        expect(node.class).toEqual('device');
        expect(node.svgClass).toEqual('node device cool');
        expect(node.id).toEqual('foo');
    });

    it('should create online device node with type', function () {
        var node = tms.createDeviceNode({ id: 'foo', type: 'cool', online: true });
        expect(node).toBePositionedAt(randLoc);
        expect(node).not.toBeFixed();
        expect(node.class).toEqual('device');
        expect(node.svgClass).toEqual('node device cool online');
        expect(node.id).toEqual('foo');
    });

    it('should create online device node with type and lng/lat', function () {
        var node = tms.createDeviceNode({
            id: 'foo',
            type: 'yowser',
            online: true,
            location: {
                type: 'lnglat',
                lng: 2048,
                lat: 3096
            }
        });
        expect(node).toBePositionedAt([48,96]);
        expect(node).toBeFixed();
        expect(node.class).toEqual('device');
        expect(node.svgClass).toEqual('node device yowser online');
        expect(node.id).toEqual('foo');
    });

    // === unit tests for createHostNode()

    it('should create a basic host node', function () {
        var node = tms.createHostNode({ id: 'bar', cp: { device: 'dev0' } });
        expect(node).toBePositionedAt(randHostLoc);
        expect(node).not.toBeFixed();
        expect(node.class).toEqual('host');
        expect(node.svgClass).toEqual('node host endstation');
        expect(node.id).toEqual('bar');
    });

    it('should create a host with type', function () {
        var node = tms.createHostNode({
            id: 'bar',
            type: 'classic',
            cp: { device: 'dev1' }
        });
        expect(node).toBePositionedAt(nearDev1);
        expect(node).not.toBeFixed();
        expect(node.class).toEqual('host');
        expect(node.svgClass).toEqual('node host classic');
        expect(node.id).toEqual('bar');
    });

    // === unit tests for createHostLink()

    it('should create a basic host link', function () {
        var link = tms.createHostLink(host1);
        expect(link.source).toEqual(host1);
        expect(link.target).toEqual(dev1);
        expect(link).toHaveEndPoints(host1Loc, dev1Loc);
        expect(link.key).toEqual('dev1/7-host1');
        expect(link.class).toEqual('link');
        expect(link.type()).toEqual('hostLink');
        expect(link.linkWidth()).toEqual(1);
        expect(link.online()).toEqual(true);
    });

    it('should return null for failed endpoint lookup', function () {
        spyOn($log, 'error');
        var link = tms.createHostLink(host2);
        expect(link).toBeNull();
        expect($log.error).toHaveBeenCalledWith(
            'Node(s) not on map for link:\n[dst] "dev0" missing'
        );
    });

    // === unit tests for createLink()

    it('should return null for missing endpoints', function () {
        spyOn($log, 'error');
        var link = tms.createLink({src: 'dev0', dst: 'dev00'});
        expect(link).toBeNull();
        expect($log.error).toHaveBeenCalledWith(
            'Node(s) not on map for link:\n[src] "dev0" missing\n[dst] "dev00" missing'
        );
    });

    xit('should create a basic link', function () {
        var linkData = {
                src: 'dev1',
                dst: 'dev2',
                id: 'baz',
                type: 'zoo',
                online: true,
                linkWidth: 1.5
            },
            link = tms.createLink(linkData);
        expect(link.source).toEqual(dev1);
        expect(link.target).toEqual(dev2);
        expect(link).toHaveEndPoints(dev1Loc, dev2Loc);
        expect(link.key).toEqual('baz');
        expect(link.class).toEqual('link');
        expect(link.fromSource).toBe(linkData);
        expect(link.type()).toEqual('zoo');
        expect(link.online()).toEqual(true);
        expect(link.linkWidth()).toEqual(1.5);
    });

    // TODO: more unit tests for additional functions....
});
