/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

import QUnit from "qunit-tests";

var angular = require("angular");
require("./connection");

(function() {
    var fixtures = [];

    var configJson;

    /* Filled in with a function */
    var inject;

    var module = angular.module("kubernetes.connection.tests", [
        "kubeClient",
        'kubeClient.cockpit',
        "kubernetes.connection",
    ]);

    function injectLoadFixtures(fixtures) {
        inject([
            "kubeLoader",
            function(loader, data) {
                loader.reset(true);
                if (fixtures)
                    loader.handle(fixtures);
            }
        ]);
    }

    QUnit.test("sessionCertificates test", function(assert) {
        var done = assert.async();
        assert.expect(5);

        injectLoadFixtures(fixtures);
        inject([
            "sessionCertificates",
            function(sessionCertificates) {
                sessionCertificates.trustCert(null, "data");
                assert.equal(sessionCertificates.getCert("localhost"), "data", "data retrive");
                assert.equal(sessionCertificates.getCert(null), "data", "null is localhost");
                sessionCertificates.trustCert({}, "data1");
                assert.equal(sessionCertificates.getCert("localhost"), "data1", "blank server retrive");
                assert.equal(sessionCertificates.getCert("address"), undefined, "missing is undefined");
                sessionCertificates.trustCert({ server: "address" }, "address-data");
                assert.equal(sessionCertificates.getCert("address"), undefined, "address data");
                done();
            }
        ]);
    });

    QUnit.test("cockpitKubectlConfig parseKubeConfig", function (assert) {
        var done = assert.async();
        assert.expect(5);

        injectLoadFixtures(fixtures);
        inject(["cockpitKubectlConfig", function (ckg) {
            var alpha = {
                "address": "alfa.org",
                "headers": {
                    "Authorization": "Bearer provider-token"
                },
                "port": 443,
                "tls": {
                    "validate": false,
                    "authority": undefined,
                    "certificate": undefined,
                    "key": undefined,
                }
            };

            var bravo = {
                "address": "bravo.org",
                "headers": {
                    "Authorization": "Bearer provider-access-token"
                },
                "port": 8080,
                "tls": {
                    "authority": {
                        "file": "cert-authority-file"
                    },
                    "certificate": undefined,
                    "key": undefined,
                    "validate": true
                }
            };

            var charlie = {
                "address": "charlie.org",
                "headers": {
                    "Authorization": "Bearer token"
                },
                "port": 8080
            };

            var delta1 = {
                "address": "delta.org",
                "headers": {},
                "port": 443,
                "tls": {
                    "authority": undefined,
                    "certificate": {
                        "file": "cert-file"
                    },
                    "key": {
                        "file": "key-file"
                    },
                    "validate": true
                }
            };

            var delta2 = {
                "address": "delta.org",
                "headers": {
                    "Authorization": "Basic dXNlcjpwYXNzd29yZA=="
                },
                "port": 443,
                "tls": {
                    "validate": true,
                    "authority": undefined,
                    "certificate": undefined,
                    "key": undefined,
                }
            };
            var configData = JSON.stringify(configJson);
            assert.deepEqual(ckg.parseKubeConfig(configData), alpha);
            assert.deepEqual(ckg.parseKubeConfig(configData, "bravo-with-access-token-auth-provider"), bravo);
            assert.deepEqual(ckg.parseKubeConfig(configData, "charlie-with-token"), charlie);
            assert.deepEqual(ckg.parseKubeConfig(configData, "delta-with-cert"), delta1);
            assert.deepEqual(ckg.parseKubeConfig(configData, "delta-with-basic"), delta2);
            done();
        }]);
    });

    QUnit.test("connectionActions prepareData", function (assert) {
        var done = assert.async();
        assert.expect(6);

        injectLoadFixtures(fixtures);
        inject(["connectionActions", function(connectionActions) {
            var cluster, context, user, data, config;
            data = connectionActions.prepareData();
            assert.deepEqual(data, {
                "cluster": {
                    "cluster": {
                        "server": "http://localhost:8080"
                    },
                    "name": "localhost:8080"
                },
                "context": {
                    "context": {
                        "cluster": "localhost:8080",
                        "user": undefined
                    },
                    "name": "localhost:8080/noauth"
                },
                "user": undefined
            }, "got right empty values");

            cluster = {
                "cluster": { "server": "https://127.0.0.1:8000" },
                "name": "name"
            };
            user = {
                "user": { "token": "token" },
                "name": "user"
            };

            context = {
                "context": {
                    "user": "user",
                    "cluster": "name"
                },
                name : "existing"
            };

            config = {
                users: [user],
                clusters: [cluster],
                contexts: [ context ]
            };

            data = connectionActions.prepareData(config, cluster, user);
            assert.deepEqual(data, {
                "cluster": {
                    "cluster": { "server": "https://127.0.0.1:8000" },
                    "name": "name"
                },
                "context": { "name" : "existing" },
                "user": {
                    "user": { "token": "token" },
                    "name": "user"
                }
            }, "matched existing");

            // remove names
            delete cluster.name;
            delete user.name;
            data = connectionActions.prepareData({}, cluster, user);
            assert.deepEqual(data, {
                "cluster": {
                    "cluster": { "server": "https://127.0.0.1:8000" },
                    "name": "127-0-0-1:8000"
                },
                "context": {
                    "name": "127-0-0-1:8000/user/127-0-0-1:8000",
                    "context": {
                        "user": "user/127-0-0-1:8000",
                        "cluster": "127-0-0-1:8000"
                    }
                },
                "user": {
                    "user": { "token": "token" },
                    "name": "user/127-0-0-1:8000"
                },
            }, "generated names");

            // No dups
            config = {
                contexts: [{ "name": "127-0-0-1:8000/user/127-0-0-1:8000" }],
            };
            data = connectionActions.prepareData(config, cluster, user);
            var pos = data.context.name.indexOf("127-0-0-1:8000/user/127-0-0-1:8000");
            assert.ok(data.context.name != "127-0-0-1:8000/user/127-0-0-1:8000" && pos === 0, "dedup context name");

            config = {
                clusters: [{ "name": "127-0-0-1:8000" }],
            };
            delete cluster.name;
            data = connectionActions.prepareData(config, cluster, user);
            pos = data.cluster.name.indexOf("127-0-0-1:8000");
            assert.ok(data.cluster.name != "127-0-0-1:8000" && pos === 0, "dedup cluster name");

            config = {
                users: [{ "name": "user/127-0-0-1:8000" }],
            };
            delete user.name;
            data = connectionActions.prepareData(config, cluster, user);
            pos = data.user.name.indexOf("user/127-0-0-1:8000");
            assert.ok(data.user.name != "user/127-0-0-1:8000" && pos === 0, "dedup user name");

            done();
        }]);
    });

    angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {
        return function(exception, cause) {
            exception.message += ' (caused by "' + cause + '")';
            throw exception;
        };
    });

    configJson = {
        "clusters": [{
            "name": "alfa",
            "cluster": {
                "insecure-skip-tls-verify": true,
                "server": "https://alfa.org"
            }
        }, {
            "name": "bravo",
            "cluster": {
                "server": "https://bravo.org:8080",
                "certificate-authority": "cert-authority-file"
            }
        }, {
            "name": "charlie",
            "cluster": {
                "server": "http://charlie.org"
            }
        }, {
            "name": "delta",
            "cluster": {
                "server": "https://delta.org:443"
            }
        }],
        "contexts": [{
            "name": "alfa-with-token-auth-provider",
            "context": {
                "cluster": "alfa",
                "user": "token-auth-provider"
            }
        }, {
            "name": "bravo-with-access-token-auth-provider",
            "context": {
                "cluster": "bravo",
                "user": "access-token-auth-provider"
            }
        }, {
            "name": "charlie-with-token",
            "context": {
                "cluster": "charlie",
                "user": "token"
            }
        }, {
            "name": "delta-with-cert",
            "context": {
                "cluster": "delta",
                "user": "cert"
            }
        }, {
            "name": "delta-with-basic",
            "context": {
                "cluster": "delta",
                "user": "basic"
            }
        }],
        "current-context": "alfa-with-token-auth-provider",
        "users": [{
            "name": "token-auth-provider",
            "user": {
                "auth-provider": {
                    "config": {
                        "token": "provider-token"
                    },
                    "name": "gcp"
                }
            }
        }, {
            "name": "access-token-auth-provider",
            "user": {
                "auth-provider": {
                    "config": {
                        "access-token": "provider-access-token"
                    },
                    "name": "gcp"
                }
            }
        }, {
            "name": "token",
            "user": {
                "token": "token"
            }
        }, {
            "name": "cert",
            "user": {
                "client-certificate": "cert-file",
                "client-key": "key-file"
            }
        }, {
            "name": "basic",
            "user": {
                "username": "user",
                "password": "password"
            }
        }]
    };

    module.run([
        '$injector',
        function($injector) {
            inject = function inject(func) {
                return $injector.invoke(func);
            };
            QUnit.start();
        }
    ]);

    angular.bootstrap(document, ['kubernetes.connection.tests']);
}());
