# Copyright 2020 ArctosLabs Scandinavia AB
#
# 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 datetime
import platform
import itertools

import pymzn
from jinja2 import Environment
from jinja2.loaders import FileSystemLoader, PackageLoader, ChoiceLoader


class MznPlacementConductor(object):
    """
    Knows how to process placement req using minizinc
    """

    if platform.system() == "Windows":
        default_mzn_path = "C:\\Program Files\\MiniZinc IDE (bundled)\\minizinc.exe"
    else:
        default_mzn_path = "/minizinc/bin/minizinc"

    def __init__(self, log, mzn_path=default_mzn_path):
        pymzn.config["minizinc"] = mzn_path
        self.log = (
            log  # FIXME what to log (besides forwarding it to MznModelGenerator) here?
        )

    def _run_placement_model(self, mzn_model, ns_desc, mzn_model_data={}):
        """
        Runs the minizinc placement model and post process the result
        Note: in this revision we use the 'item' output mode from pymzn.minizinc since it ease
        post processing of the solutions when we use enumerations in mzn_model
        Note: minizinc does not support '-' in identifiers and therefore we convert back from use of '_' when we
        process the result
        Note: minizinc does not support identifiers starting with numbers and therefore we skip the leading 'vim_'
        when we process the result

        :param mzn_model: a minizinc model as str (note: may also be path to .mzn file)
        :param ns_desc: network service descriptor, carries information about pinned VNFs so those can be included in
         the result
        :param mzn_model_data: minizinc model data dictionary (typically not used with our models)
        :return: list of dicts formatted as {'vimAccountId': '<account id>', 'member-vnf-index': <'index'>}
        or formatted as [{}] if unsatisfiable model
        """
        solns = pymzn.minizinc(mzn_model, data=mzn_model_data, output_mode="item")

        if "UNSATISFIABLE" in str(solns):
            return [{}]

        solns_as_str = str(solns[0])

        # make it easier to extract the desired information by cleaning from newline, whitespace etc.
        solns_as_str = solns_as_str.replace("\n", "").replace(" ", "").rstrip(";")

        vnf_vim_mapping = (e.split("=") for e in solns_as_str.split(";"))

        res = [
            {"vimAccountId": e[1][3:].replace("_", "-"), "member-vnf-index": e[0][3:]}
            for e in vnf_vim_mapping
        ]
        # add any pinned VNFs
        pinned = [
            {
                "vimAccountId": e["vim_account"][3:].replace("_", "-"),
                "member-vnf-index": e["vnf_id"],
            }
            for e in ns_desc
            if "vim_account" in e.keys()
        ]

        return res + pinned

    def do_placement_computation(self, nspd):
        """
        Orchestrates the placement computation

        :param nspd: placement data
        :return: see _run_placement_model
        """
        mzn_model = MznModelGenerator(self.log).create_model(nspd)
        return self._run_placement_model(mzn_model, nspd["ns_desc"])


class MznModelGenerator(object):
    """
    Has the capability to generate minizinc models from information contained in
    NsPlacementData objects. Uses jinja2 as templating language for the model
    """

    default_j2_template = "osm_pla_dynamic_template.j2"
    template_search_path = [
        "osm_pla/placement",
        "../placement",
        "/pla/osm_pla/placement",
        "./",
        "/usr/lib/python3/dist-packages/osm_pla/placement",
    ]

    def __init__(self, log):
        """
        Constructor
        """
        self.log = log  # FIXME we do not log anything so far

    def create_model(self, ns_placement_data):
        """
        Creates a minizinc model according to the content of nspd
        nspd - NSPlacementData
        return MZNModel
        """
        self.log.info("ns_desc: {}".format(ns_placement_data["ns_desc"]))
        self.log.info("vld_desc: {}".format(ns_placement_data["vld_desc"]))
        mzn_model_template = self._load_jinja_template()
        mzn_model = mzn_model_template.render(ns_placement_data)
        self.log.info("Minizinc model: {}".format(mzn_model))
        return mzn_model

    def _load_jinja_template(self, template_name=default_j2_template):
        """loads the jinja template used for model generation"""
        loader1 = FileSystemLoader(MznModelGenerator.template_search_path)
        loader2 = PackageLoader("osm_pla", ".")
        env = Environment(loader=ChoiceLoader([loader1, loader2]), autoescape=True)
        return env.get_template(template_name)


class NsPlacementDataFactory(object):
    """
    process information an network service and applicable network infrastructure resources in order to produce
    information tailored for the minizinc model code generator
    """

    def __init__(
        self,
        vim_accounts_info,
        vnf_prices,
        nsd,
        pil_info,
        pinning=None,
        order_constraints=None,
    ):
        """
        :param vim_accounts_info: a dictionary with vim url as key and id as value, we add a unique index to it for use
        in the mzn array constructs and adjust the value of the id to minizinc acceptable identifier syntax
        :param vnf_prices: a dictionary with 'vnfd-id-ref' as key and a dictionary with vim_urls: cost as value
        :param nsd: the network service descriptor
        :param pil_info: price list and metrics for PoP interconnection links
        :param pinning: list of {'member-vnf-index': '<idx>', 'vim_account': '<vim-account>'}
        :param order_constraints: any constraints provided at instantiation time
        """
        next_idx = itertools.count()
        self._vim_accounts_info = {
            k: {"id": "vim" + v.replace("-", "_"), "idx": next(next_idx)}
            for k, v in vim_accounts_info.items()
        }
        self._vnf_prices = vnf_prices
        self._nsd = nsd
        self._pil_info = pil_info
        self._pinning = pinning
        self._order_constraints = order_constraints

    def _produce_trp_link_characteristics_data(self, characteristics):
        """
        :param characteristics: one of  {pil_latency, pil_price, pil_jitter}
        :return: 2d array of requested trp_link characteristics data
        """
        if characteristics not in {"pil_latency", "pil_price", "pil_jitter"}:
            raise Exception("characteristic '{}' not supported".format(characteristics))
        num_vims = len(self._vim_accounts_info)
        trp_link_characteristics = [
            [0 if col == row else 0x7FFF for col in range(num_vims)]
            for row in range(num_vims)
        ]
        for pil in self._pil_info["pil"]:
            if characteristics in pil.keys():
                ep1 = pil["pil_endpoints"][0]
                ep2 = pil["pil_endpoints"][1]
                # only consider links between applicable vims
                if ep1 in self._vim_accounts_info and ep2 in self._vim_accounts_info:
                    idx1 = self._vim_accounts_info[ep1]["idx"]
                    idx2 = self._vim_accounts_info[ep2]["idx"]
                    trp_link_characteristics[idx1][idx2] = pil[characteristics]
                    trp_link_characteristics[idx2][idx1] = pil[characteristics]

        return trp_link_characteristics

    # TODO: Review if we should adapt this method with SOL006 /nsd/vnfd/int-virtual-link-desc/df/qos fields.
    def _produce_vld_desc(self):
        """
        Creates the expected vlds from the nsd. Includes constraints if part of nsd.
        Overrides constraints with any syntactically correct instantiation parameters
        :return:
        """

        all_vld_member_vnf_index_refs = {}
        # TODO: Change for multiple DF support
        ns_df = self._nsd.get("df", [{}])[0]
        for vnf_profile in ns_df.get("vnf-profile", []):
            for vlc in vnf_profile.get("virtual-link-connectivity", []):
                vld_id = vlc.get("virtual-link-profile-id")
                vld_member_vnf_index_ref = vnf_profile.get("id")
                if vld_id in all_vld_member_vnf_index_refs:
                    all_vld_member_vnf_index_refs[vld_id].append(
                        vld_member_vnf_index_ref
                    )
                else:
                    all_vld_member_vnf_index_refs[vld_id] = [vld_member_vnf_index_ref]

        vld_desc = []
        for vld in self._nsd.get("virtual-link-desc", ()):
            if vld.get("mgmt-network", False) is True:
                continue
            vld_desc_entry = {}
            cp_refs = all_vld_member_vnf_index_refs[vld.get("id")]
            if len(cp_refs) == 2:
                vld_desc_entry["cp_refs"] = cp_refs
                # TODO: Change for multiple DF support
                vld_df = vld.get("df", [{}])[0]
                for constraint in vld_df.get("qos", {}):
                    if constraint == "latency":
                        vld_desc_entry["latency"] = vld_df["qos"][constraint]
                    elif constraint == "packet-delay-variation":
                        vld_desc_entry["jitter"] = vld_df["qos"][constraint]
                vld_desc.append(vld_desc_entry)

        # create candidates from instantiate params
        if self._order_constraints is not None:
            candidate_vld_desc = []
            # use id to find the endpoints in the nsd
            for entry in self._order_constraints.get("vld-constraints"):
                for vld in self._nsd.get("virtual-link-desc", ()):
                    if entry["id"] == vld.get("id"):
                        vld_desc_instantiate_entry = {}
                        cp_refs = all_vld_member_vnf_index_refs[vld.get("id")]
                        vld_desc_instantiate_entry["cp_refs"] = cp_refs
                        # add whatever constraints that are provided to the vld_desc_entry
                        # misspelled 'link-constraints' => empty dict
                        # lack (or misspelling) of one or both supported constraints => entry not appended
                        for constraint, value in entry.get(
                            "link-constraints", {}
                        ).items():
                            if constraint == "latency":
                                vld_desc_instantiate_entry["latency"] = value
                            elif constraint == "jitter":
                                vld_desc_instantiate_entry["jitter"] = value
                        if {"latency", "jitter"}.intersection(
                            vld_desc_instantiate_entry.keys()
                        ):
                            candidate_vld_desc.append(vld_desc_instantiate_entry)
            # merge with nsd originated, FIXME log any deviations?
            for vld_d in vld_desc:
                for vld_d_i in candidate_vld_desc:
                    if set(vld_d["cp_refs"]) == set(vld_d_i["cp_refs"]):
                        if vld_d_i.get("jitter"):
                            vld_d["jitter"] = vld_d_i["jitter"]
                        if vld_d_i.get("latency"):
                            vld_d["latency"] = vld_d_i["latency"]

        return vld_desc

    def _produce_ns_desc(self):
        """
        collect information for the ns_desc part of the placement data
        for the vim_accounts that are applicable, collect the vnf_price
        """
        ns_desc = []
        # TODO: Change for multiple DF support
        ns_df = self._nsd.get("df", [{}])[0]
        for vnf_profile in ns_df.get("vnf-profile", []):
            vnf_info = {"vnf_id": vnf_profile["id"]}
            # prices
            prices_for_vnfd = self._vnf_prices[vnf_profile["vnfd-id"]]
            # the list of prices must be ordered according to the indexing of the vim_accounts
            price_list = [_ for _ in range(len(self._vim_accounts_info))]
            for k in prices_for_vnfd.keys():
                if k in self._vim_accounts_info.keys():
                    price_list[self._vim_accounts_info[k]["idx"]] = prices_for_vnfd[k]
            vnf_info["vnf_price_per_vim"] = price_list

            # pinning to dc
            if self._pinning is not None:
                for pinned_vnf in self._pinning:
                    if vnf_profile["id"] == pinned_vnf["member-vnf-index"]:
                        vnf_info["vim_account"] = "vim" + pinned_vnf[
                            "vimAccountId"
                        ].replace("-", "_")

            ns_desc.append(vnf_info)
        return ns_desc

    def create_ns_placement_data(self):
        """populate NsPlacmentData object"""
        ns_placement_data = {
            "vim_accounts": [
                vim_data["id"]
                for _, vim_data in sorted(
                    self._vim_accounts_info.items(), key=lambda item: item[1]["idx"]
                )
            ],
            "trp_link_latency": self._produce_trp_link_characteristics_data(
                "pil_latency"
            ),
            "trp_link_jitter": self._produce_trp_link_characteristics_data(
                "pil_jitter"
            ),
            "trp_link_price_list": self._produce_trp_link_characteristics_data(
                "pil_price"
            ),
            "ns_desc": self._produce_ns_desc(),
            "vld_desc": self._produce_vld_desc(),
            "generator_data": {"file": __file__, "time": datetime.datetime.now()},
        }

        return ns_placement_data
