# Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This library 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.
#
# This library 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 this library.  If not, see <http://www.gnu.org/licenses/>.

from pathlib import Path
from typing import List

from vyos.xml_ref import load_reference
from vyos.base import Warning as Warn

def priority_data(d: dict) -> list:
    def func(d, path, res, hier):
        for k,v in d.items():
            if not 'node_data' in v:
                continue
            subpath = path + [k]
            hier_prio = hier
            data = v.get('node_data')
            o = data.get('owner')
            p = data.get('priority')
            # a few interface-definitions have priority preceding owner
            # attribute, instead of within properties; pass in descent
            if p is not None and o is None:
                hier_prio = p
            if o is not None and p is None:
                p = hier_prio
            if o is not None and p is not None:
                o = Path(o.split()[0]).name
                p = int(p)
                res.append((subpath, o, p))
            if isinstance(v, dict):
                func(v, subpath, res, hier_prio)
        return res
    ret = func(d, [], [], 0)
    ret = sorted(ret, key=lambda x: x[0])
    ret = sorted(ret, key=lambda x: x[2])
    return ret

def get_priority_data() -> list:
    xml = load_reference()
    return priority_data(xml.ref)

def priority_sort(sections: List[list[str]] = None,
                  owners: List[str] = None,
                  reverse=False) -> List:
    if sections is not None:
        index = 0
        collection: List = sections
    elif owners is not None:
        index = 1
        collection = owners
    else:
        raise ValueError('one of sections or owners is required')

    l = get_priority_data()
    m = [item for item in l if item[index] in collection]
    n = sorted(m, key=lambda x: x[2], reverse=reverse)
    o = [item[index] for item in n]
    # sections are unhashable; use comprehension
    missed = [j for j in collection if j not in o]
    if missed:
        Warn(f'No priority available for elements {missed}')

    return o