#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
    This script is a wrapper around update-alternatives utility.
    Its goal is to change all links managed by update-alternatives for a package

    Call the script with the package name as first argument
"""
from os import listdir
from os.path import isfile, join
from os.path import basename
from subprocess import call
import sys
import re

class LinkUA:
    """
        This class manage a link
        Each link is described in a file and each can have many path
        (binary providing the same functionnality)
    """
    def __init__(self, filename):
        self.__name = ""
        self.__link = ""
        self.__paths = {}
        self.__filename = filename
        self.__regexp = re.compile(r".*\." + re.escape(pkg_name) + r"$")
        with open(filename, 'r') as f:
            lines = f.readlines()
            if len(lines) > 0 :
                self.__link = lines.pop(0).strip()
                self.__name = basename(filename)
                for path in lines:
                    path_info = path.split()
                    self.__paths[path_info[0]] = int(path_info[1])

    def raise_priority(self, pkg_name):
        """
            Force the pkg_name version to be used by raising its priority
        """
        # First check if package is in the alternative path
        if ( self.filter(pkg_name) ):
            #To raise we have to know the maximum existing priority
            max_priority = max(list(self.__paths.values()))
            complete_path = self.path_from_pkg_name(pkg_name)
            my_priority = self.__paths[ complete_path ]
            #print("Max %d, my %d"%(max_priority, my_priority))
            if my_priority < max_priority:
                #print("Raising priority to %d"%self.__paths[ complete_path ])
                call(["update-alternatives", "--remove", self.__name, complete_path])
                call(["update-alternatives", "--install", self.__link, self.__name, complete_path, str(max_priority+1)])

    def path_from_pkg_name(self, pkg_name):
        """
            Return the complete path for a pak_name.
            If there is no path for this name, an empty string is returned
        """
        for path in self.__paths:
            if self.__regexp.match(path) != None:
                return path
        return ""

    def filter(self, pkg_name):
        """
            Filter function returning if a path exists for the given pkg_name
        """
        return self.path_from_pkg_name(pkg_name) != ""

if __name__ == "__main__":
    ua_path = "/usr/lib/opkg/alternatives"
    if len(sys.argv) == 2:
        pkg_name = sys.argv[1]
        onlyfiles = [join(ua_path, f) for f in listdir(ua_path) if isfile(join(ua_path, f))]
        link_ua_list = list(map(LinkUA, onlyfiles))
        link_ua_list = [ link_ua for link_ua in link_ua_list if link_ua.filter(pkg_name) ]
        for link_ua in link_ua_list:
            link_ua.raise_priority(pkg_name)
        exit(0)
    else:
        print("Usage : one argument required, package name")
        exit(-1)