#!/usr/bin/python3
#
# GPOA - GPO Applier for Linux
#
# Copyright (C) 2019-2020 BaseALT Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import rpm
import subprocess
from gpoa.storage import registry_factory
from util.util import get_uid_by_username, string_to_literal_eval
import logging
from util.logging import log
import argparse
import gettext
import locale


def is_rpm_installed(rpm_name):
    '''
    Check if the package named 'rpm_name' is installed
    '''
    ts = rpm.TransactionSet()
    pm = ts.dbMatch('name', rpm_name)
    if pm.count() > 0:
        return True

    return False

class Pkcon_applier:

    def __init__(self, user = None):
        install_key_name = 'Install'
        remove_key_name = 'Remove'
        hklm_branch = 'Software/BaseALT/Policies/Packages'
        self.__install_command = ['/usr/bin/pkcon', '-y', 'install']
        self.__remove_command = ['/usr/bin/pkcon', '-y', 'remove']
        self.__reinstall_command = ['/usr/bin/pkcon', '-y', 'reinstall']
        self.install_packages = set()
        self.remove_packages = set()
        self.storage = registry_factory()
        if user:
            uid = get_uid_by_username(user)
            dict_dconf_db = self.storage.get_dictionary_from_dconf_file_db(uid)
        else:
            dict_dconf_db = self.storage.get_dictionary_from_dconf_file_db()
        dict_packages = dict_dconf_db.get(hklm_branch,{})
        self.install_packages_setting = string_to_literal_eval(dict_packages.get(install_key_name,[]))
        self.remove_packages_setting = string_to_literal_eval(dict_packages.get(remove_key_name,[]))

        for package in self.install_packages_setting:
            package = package.strip()
            if not is_rpm_installed(package):
                self.install_packages.add(package)
        for package in self.remove_packages_setting:
            package = package.strip()
            if package in self.install_packages:
                self.install_packages.remove(package)
            if is_rpm_installed(package):
                self.remove_packages.add(package)

    def apply(self):
        log('D142')
        self.update()
        for package in self.remove_packages:
            logdata = {'name': package}
            try:
                log('D149', logdata)
                self.remove_pkg(package)
            except Exception as exc:
                logdata['exc'] = exc
                log('E58', logdata)

        for package in self.install_packages:
           logdata = {'name': package}
           try:
                log('D148', logdata)
                self.install_pkg(package)
           except Exception as exc:
                logdata['exc'] = exc
                log('E57', logdata)


    def install_pkg(self, package_name):
        fullcmd = list(self.__install_command)
        fullcmd.append(package_name)
        return subprocess.check_output(fullcmd)

    def reinstall_pkg(self, package_name):
        pass

    def remove_pkg(self, package_name):
        fullcmd = list(self.__remove_command)
        fullcmd.append(package_name)
        return subprocess.check_output(fullcmd)

    def update(self):
        '''
        Update APT-RPM database.
        '''
        try:
            res =  subprocess.check_output(['/usr/bin/apt-get', 'update'], encoding='utf-8')
            msg =  str(res).split('\n')
            logdata = {}
            for mslog in msg:
                ms =  str(mslog).split(' ')
                if ms:
                    logdata = {ms[0]: ms[1:-1]}
                log('D143', logdata)
        except Exception as exc:
            logdata = {'msg': exc}
            log('E56',logdata)

if __name__ == '__main__':
    locale.bindtextdomain('gpoa', '/usr/lib/python3/site-packages/gpoa/locale')
    gettext.bindtextdomain('gpoa', '/usr/lib/python3/site-packages/gpoa/locale')
    gettext.textdomain('gpoa')
    logger = logging.getLogger()
    parser = argparse.ArgumentParser(description='Package applier')
    parser.add_argument('--user', type = str, help = 'user', nargs = '?', default = None)
    parser.add_argument('--loglevel', type = int, help = 'loglevel', nargs = '?', default = 30)

    args = parser.parse_args()
    logger.setLevel(args.loglevel)
    if args.user:
        applier = Pkcon_applier(args.user)
    else:
        applier = Pkcon_applier()
    applier.apply()

