# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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 sys

from libcloud.test import MockHttp, unittest
from libcloud.utils.py3 import httplib
from libcloud.test.secrets import CONTAINER_PARAMS_LXD
from libcloud.container.base import Container, ContainerImage
from libcloud.test.file_fixtures import ContainerFileFixtures
from libcloud.container.drivers.lxd import (
    LXDServerInfo,
    LXDStoragePool,
    LXDAPIException,
    LXDContainerDriver,
)


class LXDContainerDriverTestCase(unittest.TestCase):

    """
    Unit tests for LXDContainerDriver
    """

    def setUp(self):
        # Create a test driver for each version
        versions = ("linux_124",)
        self.drivers = []
        for version in versions:
            LXDContainerDriver.connectionCls.conn_class = LXDMockHttp
            LXDMockHttp.type = None
            LXDMockHttp.use_param = "a"
            driver = LXDContainerDriver(*CONTAINER_PARAMS_LXD)
            driver.connectionCls.conn_class = LXDMockHttp
            driver.version = version
            self.drivers.append(driver)

    def test_ex_get_api_endpoints_trusted(self):
        for driver in self.drivers:
            api = driver.ex_get_api_endpoints()
            self.assertEqual(api[0], driver.version)

    def test_ex_get_server_configuration(self):
        for driver in self.drivers:
            server_config = driver.ex_get_server_configuration()
            self.assertIsInstance(server_config, LXDServerInfo)
            self.assertEqual(server_config.api_extensions, [])
            self.assertEqual(server_config.api_status, "stable")
            self.assertEqual(server_config.api_version, "linux_124")
            self.assertEqual(server_config.auth, "guest")
            self.assertEqual(server_config.public, False)

    def test_list_images(self):
        img_id = "54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473"
        for driver in self.drivers:
            images = driver.list_images()
            self.assertEqual(len(images), 1)
            self.assertIsInstance(images[0], ContainerImage)
            self.assertEqual(images[0].id, img_id)
            self.assertEqual(images[0].name, "trusty")

    def test_list_containers(self):
        for driver in self.drivers:
            containers = driver.list_containers()
            self.assertEqual(len(containers), 2)
            self.assertIsInstance(containers[0], Container)
            self.assertIsInstance(containers[1], Container)
            self.assertEqual(containers[0].name, "first_lxd_container")
            self.assertEqual(containers[1].name, "second_lxd_container")

    def test_get_container(self):
        for driver in self.drivers:
            container = driver.get_container(id="second_lxd_container")
            self.assertIsInstance(container, Container)
            self.assertEqual(container.name, "second_lxd_container")
            self.assertEqual(container.id, "second_lxd_container")
            self.assertEqual(container.state, "stopped")

    def test_start_container(self):
        for driver in self.drivers:
            container = driver.get_container(id="first_lxd_container")
            container.start()
            self.assertEqual(container.state, "running")

    def test_stop_container(self):
        for driver in self.drivers:
            container = driver.get_container(id="second_lxd_container")
            container.stop()
            self.assertEqual(container.state, "stopped")

    def test_restart_container(self):
        for driver in self.drivers:
            container = driver.get_container(id="second_lxd_container")
            container.restart()

    def test_delete_container(self):
        for driver in self.drivers:
            container = driver.get_container(id="second_lxd_container")
            container.destroy()

    def test_deploy_container(self):
        for driver in self.drivers:
            image = ContainerImage(id=None, name=None, path=None, version=None, driver=driver)
            container = driver.deploy_container(
                name="first_lxd_container",
                image=image,
                parameters='{"source":{"type":"image", '
                '"fingerprint":"7ed08b435c92cd8a8a884c88e8722f2e7546a51e891982a90ea9c15619d7df9b"}}',
            )
            self.assertIsInstance(container, Container)
            self.assertEqual(container.name, "first_lxd_container")

    # test images
    def test_install_image_no_dict(self):
        with self.assertRaises(LXDAPIException) as exc:
            for driver in self.drivers:
                driver.install_image(path=None)
                self.assertEqual(
                    str(exc),
                    "Install an image for LXD requires specification of image_data",
                )

    # test storage pools

    def test_list_storage_pools(self):
        for driver in self.drivers:
            pools = driver.ex_list_storage_pools()
            self.assertEqual(len(pools), 2)
            self.assertIsInstance(pools[0], LXDStoragePool)
            self.assertIsInstance(pools[1], LXDStoragePool)
            self.assertEqual(pools[0].name, "pool1")
            self.assertEqual(pools[1].name, "pool2")

    def test_get_storage_pool_no_metadata(self):
        with self.assertRaises(LXDAPIException) as exc:
            for driver in self.drivers:
                driver.ex_get_storage_pool(id="pool3")
                self.assertEqual(str(exc), "Storage pool with name pool3 has no data")

    def test_delete_storage_pool(self):
        for driver in self.drivers:
            driver.ex_delete_storage_pool(id="pool1")

    def test_delete_storage_pool_fail(self):
        with self.assertRaises(LXDAPIException):
            for driver in self.drivers:
                driver.ex_delete_storage_pool(id="pool2")


class LXDMockHttp(MockHttp):
    fixtures = ContainerFileFixtures("lxd")
    version = None

    def _version(self, method, url, body, headers):
        if method == "GET":
            body = self.fixtures.load("linux_124/version.json")
        else:
            raise AssertionError("Unsupported method")
        return (httplib.OK, body, {}, httplib.responses[httplib.OK])

    def root(self, method, url, body, headers):
        json = self.fixtures.load("linux_124/endpoints_sucess.json")
        return (httplib.OK, json, {}, httplib.responses[httplib.OK])

    def _linux_124(self, method, url, body, headers):
        return (
            httplib.OK,
            self.fixtures.load("linux_124/version.json"),
            {},
            httplib.responses[httplib.OK],
        )

    def _linux_124_images(self, method, url, body, headers):
        return (
            httplib.OK,
            self.fixtures.load("linux_124/images.json"),
            {},
            httplib.responses[httplib.OK],
        )

    def _linux_124_images_54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473(
        self, method, url, body, headers
    ):
        return (
            httplib.OK,
            self.fixtures.load("linux_124/image.json"),
            {},
            httplib.responses[httplib.OK],
        )

    def _linux_124_containers(self, method, url, body, headers):

        if method == "GET":
            return (
                httplib.OK,
                self.fixtures.load("linux_124/containers.json"),
                {},
                httplib.responses[httplib.OK],
            )
        elif method == "POST" or method == "PUT":
            # we do a POST when we create a container
            # we will return a dummy background operation
            return (
                httplib.OK,
                self.fixtures.load("linux_124/background_op.json"),
                {},
                httplib.responses[httplib.OK],
            )

    def _linux_124_containers_first_lxd_container(self, method, url, body, headers):
        return (
            httplib.OK,
            self.fixtures.load("linux_124/first_lxd_container.json"),
            {},
            httplib.responses[httplib.OK],
        )

    def _linux_124_containers_second_lxd_container(self, method, url, body, headers):

        if method == "PUT" or method == "DELETE":
            json = self.fixtures.load("linux_124/background_op.json")
            return (httplib.OK, json, {}, httplib.responses[httplib.OK])
        elif method == "GET":
            return (
                httplib.OK,
                self.fixtures.load("linux_124/second_lxd_container.json"),
                {},
                httplib.responses[httplib.OK],
            )

    def _linux_124_containers_first_lxd_container_state(self, method, url, body, headers):

        if method == "PUT" or method == "DELETE":
            json = self.fixtures.load("linux_124/background_op.json")
            return (httplib.OK, json, {}, httplib.responses[httplib.OK])
        elif method == "GET":
            json = self.fixtures.load("linux_124/first_lxd_container.json")
            return (httplib.OK, json, {}, httplib.responses[httplib.OK])

    def _linux_124_containers_second_lxd_container_state(self, method, url, body, headers):

        if method == "PUT" or method == "DELETE":
            json = self.fixtures.load("linux_124/background_op.json")
            return (httplib.OK, json, {}, httplib.responses[httplib.OK])
        elif method == "GET":
            json = self.fixtures.load("linux_124/second_lxd_container.json")
            return (httplib.OK, json, {}, httplib.responses[httplib.OK])

    def _linux_124_operations_1_wait(self, method, url, body, header):
        return (
            httplib.OK,
            self.fixtures.load("linux_124/operation_1_wait.json"),
            {},
            httplib.responses[httplib.OK],
        )

    def _linux_124_storage_pools(self, method, url, body, header):

        if method == "GET":
            json = self.fixtures.load("linux_124/storage_pools.json")
            return (httplib.OK, json, {}, httplib.responses[httplib.OK])

    def _linux_124_storage_pools_pool1(self, method, url, body, header):

        if method == "GET":
            json = self.fixtures.load("linux_124/storage_pool_1.json")
            return (httplib.OK, json, {}, httplib.responses[httplib.OK])
        elif method == "DELETE":
            return (
                httplib.OK,
                self.fixtures.load("linux_124/storage_pool_delete_sucess.json"),
                {},
                httplib.responses[httplib.OK],
            )

    def _linux_124_storage_pools_pool2(self, method, url, body, header):

        if method == "GET":
            json = self.fixtures.load("linux_124/storage_pool_2.json")
            return (httplib.OK, json, {}, httplib.responses[httplib.OK])
        elif method == "DELETE":
            return (
                httplib.OK,
                self.fixtures.load("linux_124/storage_pool_delete_fail.json"),
                {},
                httplib.responses[httplib.OK],
            )

    def _linux_124_storage_pools_pool3(self, method, url, body, header):

        if method == "GET":
            json = self.fixtures.load("linux_124/no_meta_pool.json")
            return (httplib.OK, json, {}, httplib.responses[httplib.OK])

    """
    def _vlinux_124_containers_create(
        self, method, url, body, headers):
        return (httplib.OK, self.fixtures.load('linux_124/create_container.json'), {}, httplib.responses[httplib.OK])

    def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303(
        self, method, url, body, headers):
        return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK])

    def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_start(
        self, method, url, body, headers):
        return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK])

    def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_restart(
        self, method, url, body, headers):
        return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK])

    def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_rename(
        self, method, url, body, headers):
        return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK])

    def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_stop(
        self, method, url, body, headers):
        return (httplib.NO_CONTENT, '', {}, httplib.responses[httplib.OK])

    def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_json(
        self, method, url, body, headers):
        return (httplib.OK, self.fixtures.load('linux_124/container_a68.json'), {}, httplib.responses[httplib.OK])

    def _vlinux_124_containers_a68c1872c74630522c7aa74b85558b06824c5e672cee334296c50fb209825303_logs(
        self, method, url, body, headers):
        return (httplib.OK, self.fixtures.load('linux_124/logs.txt'), {'content-type': 'text/plain'},
                httplib.responses[httplib.OK])
    """


if __name__ == "__main__":
    sys.exit(unittest.main())
