#!/usr/bin/python3

import subprocess
import sys
import json
from softwareproperties.SoftwareProperties \
  import SoftwareProperties, shortcut_handler
import aptsources
import platform

'''
 Should replace apt command with python-apt module.
'''

def add_repos(repos, key_commands):

    if not repos: return 0

    release_code = platform.dist()[2]    # → xenial, yakkety, zesty

    if "all" in repos : repos = repos["all"]
    else : repos = repos.get(release_code)

    # possibly repo is not required for this release
    if not repos: return 0

    sp = SoftwareProperties()

    for repo in repos:
        # check if its a component that should be added/removed
        distro = aptsources.distro.get_distro()
        distro.get_sources(sp.sourceslist)
        components = [comp.name for comp in distro.source_template.components]
        if repo in components:
            if repo not in distro.enabled_comps:
                distro.enable_component(repo)
        else:
            sp.add_source_from_shortcut(shortcut_handler(repo))
    sp.sourceslist.save()

    if key_commands:
        for key_command in key_commands:
            subprocess.call(key_command, shell=True)

    # Update always. Ideally, this should be done only if a new repo is added
    # to list
    p = subprocess.Popen(['apt', 'update'])

    return p.wait()

def install(fname, code):
    info = pdata.getPackageInfo(fname, code)
    repos = info.get("repos")
    packages = info.get("packages")
    excludes = info.get("excludes")
    key_commands = info.get("key-commands")

    retval = add_repos(repos, key_commands)

    if excludes != None:
        for exclude in excludes:
            packages.append(exclude + '-')

    if packages:
        process = subprocess.Popen(['apt', 'install', '--allow-unauthenticated', '-y'] + packages)
        retval += process.wait()

    return retval

def remove(fname, code):
    info = pdata.getPackageInfo(fname, code)
    packages = info["packages"]

    process = subprocess.Popen(['apt', 'remove', '-y'] + packages)

    retval = process.wait()

    return retval

def run_script(fname):

    process = subprocess.Popen(['sh', fname])

    retval = process.wait()

    return retval

class PackageData(object):

    def __init__(self, json_path):
        # app._data_path + "/config/packages.json"
        with open(json_path) as file:
            self.data = json.load(file)


    def getPackageInfo(self, filename, code):
        try:
            return self.data[filename][code]
        except KeyError as e:
            print(e)
            return None

if __name__ == "__main__":
    '''
        args[1]  action to perform (INSTALL/REMOVE/SCRIPT)
        args[2]  file name in which package is listed
        args[3]  code name for package
        args[4]  path to json file containing package details
    '''

    args = sys.argv

    if len(args) < 5:
        print("Expected arguments not found")
        sys.exit(-1)

    action = args[1]
    fname = args[2]
    code = args[3]
    json_path = args[4]

    pdata = PackageData(json_path)

    if action == 'INSTALL':
        retval = install(fname, code)
    elif action == 'REMOVE':
        retval = remove(fname, code)
    elif action == 'SCRIPT':
        # fname -> script name, code -> requires root privilege?
        retval = run_script(fname, code)
    sys.exit(retval)
