# 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.


from xosconfig import Config
from functools import reduce


def f7(seq):
    seen = set()
    seen_add = seen.add
    return [x for x in seq if not (x in seen or seen_add(x))]


def elim_dups(backend_str):
    strs = backend_str.split(" // ")
    strs2 = f7(strs)
    return " // ".join(strs2)


def deepgetattr(obj, attr):
    return reduce(getattr, attr.split("."), obj)


def obj_class_name(obj):
    return getattr(obj, "model_name", obj.__class__.__name__)


class InnocuousException(Exception):
    pass


class DeferredException(Exception):
    pass


class FailedDependency(Exception):
    pass


class SyncStep(object):
    """ An XOS Sync step.

    Attributes:
        psmodel        Model name the step synchronizes
        dependencies    list of names of models that must be synchronized first if the current model depends on them
    """

    # map_sync_outputs can return this value to cause a step to be marked
    # successful without running ansible. Used for sync_network_controllers
    # on nat networks.
    SYNC_WITHOUT_RUNNING = "sync_without_running"

    slow = False

    def get_prop(self, prop):
        # NOTE config_dir is never define, is this used?
        sync_config_dir = Config.get("config_dir")
        prop_config_path = "/".join(sync_config_dir, self.name, prop)
        return open(prop_config_path).read().rstrip()

    def __init__(self, **args):
        """Initialize a sync step
           Keyword arguments:
               model_accessor: class used to access models
               driver: used by openstack synchronizer (DEPRECATED)
               error_map: used by openstack synchronizer (DEPRECATED)
        """
        self.model_accessor = args.get("model_accessor")
        self.driver = args.get("driver")
        self.error_map = args.get("error_map")

        assert self.model_accessor is not None

        try:
            self.soft_deadline = int(self.get_prop("soft_deadline_seconds"))
        except BaseException:
            self.soft_deadline = 5  # 5 seconds

        if "log" in args:
            self.log = args.get("log")

        return

    @property
    def observes_classes(self):
        """ Return a list of classes that this syncstep observes. The "observes" class member can be either a list of
            items or a single item. Those items may be either classes or names of classes. This function always returns
            a list of classes.
        """
        if not self.observes:
            return []
        if isinstance(self.observes, list):
            observes = self.observes
        else:
            observes = [self.observes]
        result = []
        for class_or_name in observes:
            if isinstance(class_or_name, str):
                result.append(self.model_accessor.get_model_class(class_or_name))
            else:
                result.append(class_or_name)
        return result


    def fetch_pending(self, deletion=False):
        # This is the most common implementation of fetch_pending
        # Steps should override it if they have their own logic
        # for figuring out what objects are outstanding.

        return self.model_accessor.fetch_pending(self.observes_classes, deletion)


    def sync_record(self, o):
        self.log.debug("In abstract sync record", **o.tologdict())
        # This method should be overridden by the service


    def delete_record(self, o):
        self.log.debug("In abstract delete record", **o.tologdict())
        # This method should be overridden by the service
