# Copyright 2017-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 unittest
from mock import patch
import mock
import pdb
import networkx as nx

import os
import sys

test_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
sync_lib_dir = os.path.join(test_path, "..", "xossynchronizer")
xos_dir = os.path.join(test_path, "..", "..", "..", "xos")

class TestScheduling(unittest.TestCase):
    def setUp(self):
        self.sys_path_save = sys.path
        self.cwd_save = os.getcwd()

        config = os.path.join(test_path, "test_config.yaml")
        from xosconfig import Config

        Config.clear()
        Config.init(config, "synchronizer-config-schema.yaml")

        from xossynchronizer.mock_modelaccessor_build import (
            build_mock_modelaccessor,
        )

        build_mock_modelaccessor(sync_lib_dir, xos_dir, services_dir=None, service_xprotos=[])

        # The test config.yaml references files in `test/` so make sure we're in the parent directory of the
        # test directory.
        os.chdir(os.path.join(test_path, ".."))

        import xossynchronizer.event_loop
        reload(xossynchronizer.event_loop)

        import xossynchronizer.backend
        reload(xossynchronizer.backend)

        from xossynchronizer.modelaccessor import model_accessor

        b = xossynchronizer.backend.Backend(model_accessor=model_accessor)
        steps_dir = Config.get("steps_dir")
        self.steps = b.load_sync_step_modules(steps_dir)
        self.synchronizer = xossynchronizer.event_loop.XOSObserver(self.steps, model_accessor)

    def tearDown(self):
        sys.path = self.sys_path_save
        os.chdir(self.cwd_save)

    def test_load_steps(self):
        step_names = [s.__name__ for s in self.steps]
        self.assertIn("SyncControllerSlices", step_names)

    def test_load_deps(self):
        self.synchronizer.load_dependency_graph()
        graph = self.synchronizer.model_dependency_graph
        self.assertTrue(graph[False].has_edge("Instance", "Slice"))
        self.assertTrue(graph[True].has_edge("Slice", "Instance"))
        self.assertTrue(graph[False].has_edge("Slice", "ControllerSlice"))
        self.assertTrue(graph[True].has_edge("ControllerSlice", "Slice"))

    def test_load_dep_accessors(self):
        self.synchronizer.load_dependency_graph()
        graph = self.synchronizer.model_dependency_graph
        self.assertDictContainsSubset(
            {"src_accessor": "controllerslices"},
            graph[False]["Slice"]["ControllerSlice"],
        )
        self.assertDictContainsSubset(
            {"src_accessor": "slice", "dst_accessor": "controllerslices"},
            graph[True]["Slice"]["ControllerSlice"],
        )

    def test_load_sync_steps(self):
        self.synchronizer.load_sync_steps()
        model_to_step = self.synchronizer.model_to_step
        step_lookup = self.synchronizer.step_lookup
        self.assertIn(
            ("ControllerSlice", ["SyncControllerSlices"]), model_to_step.items()
        )
        self.assertIn(
            ("Port", ["SyncPort"]), model_to_step.items()
        )
        self.assertIn(("SiteRole", ["SyncRoles"]), model_to_step.items())

        for k, v in model_to_step.items():
            val = v[0]
            observes = step_lookup[val].observes
            if not isinstance(observes, list):
                observes = [observes]

            observed_names = []
            for o in observes:
                if isinstance(o,str):
                    observed_names.append(o)
                else:
                    observed_names.append(o.__name__)

            self.assertIn(k, observed_names)


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