#!/usr/bin/python3
#this is treeview branch

import sys, os, io, subprocess
import json
import apt
from PyQt5 import QtWidgets, QtGui, QtCore, QtDBus
from collections import OrderedDict

cache = apt.cache.Cache()

def subprocess_wrap(what):
    proc = subprocess.Popen(what, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while True:
        status = proc.poll()
        if status is not None:
            break
        output = proc.stdout.readline()
        if output == '' and status:
            break
        if output:
            print(output.strip().decode('utf-8'))
    rc = proc.poll()
    print("Subprocess exited with status", rc)
    return rc

def get_mountpoint(dev):
    iface = QtDBus.QDBusInterface("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2/block_devices/%s"%(dev,), "org.freedesktop.DBus.Properties", QtDBus.QDBusConnection.systemBus())
    msg = iface.call("Get", "org.freedesktop.UDisks2.Filesystem", "MountPoints")
    mpoint = msg.arguments()[0][0].data().decode('utf-8')[:-1]
    print(mpoint)
    return mpoint

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(700, 500)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.treeView = QtWidgets.QTreeView(self.centralwidget)
        self.treeView.setGeometry(QtCore.QRect(10, 10, 781, 521))
        self.treeView.header().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
        self.treeView.setHeaderHidden(True)
        self.gridLayout.addWidget(self.treeView, 0, 0, 1, 4)
        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.hide()
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.gridLayout.addWidget(self.progressBar, 2, 0, 1, 1)
        self.btnr = QtWidgets.QPushButton(self.centralwidget)
        self.btnr.setObjectName("btnr")
        self.gridLayout.addWidget(self.btnr, 2, 2, 1, 1)
        self.btnl = QtWidgets.QPushButton(self.centralwidget)
        self.btnl.setObjectName("btnl")
        self.gridLayout.addWidget(self.btnl, 2, 1, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 600, 22))
        self.menubar.setObjectName("menubar")
        self.menuFile = QtWidgets.QMenu(self.menubar)
        self.menuFile.setObjectName("menuFile")
        self.menuAbout = QtWidgets.QMenu(self.menubar)
        self.menuAbout.setObjectName("menuAbout")
        MainWindow.setMenuBar(self.menubar)
        self.actionQuit = QtWidgets.QAction(MainWindow)
        self.actionQuit.setObjectName("actionQuit")
        self.actionInfo = QtWidgets.QAction(MainWindow)
        self.actionInfo.setObjectName("actionInfo")
        self.menuAbout.addAction(self.actionInfo)
        self.menubar.addAction(self.menuFile.menuAction())
        self.menubar.addAction(self.menuAbout.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.btnr.setText(_translate("MainWindow", "&Quit"))
        self.btnl.setText(_translate("MainWindow", "&Install"))
        self.menuFile.setTitle(_translate("MainWindow", "&File"))
        self.menuAbout.setTitle(_translate("MainWindow", "&About"))
        self.actionQuit.setText(_translate("MainWindow", "&Quit"))
        self.actionInfo.setText(_translate("MainWindow", "&Info"))

class Main(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        extractAction = QtWidgets.QAction("&Quit", self)
        extractAction.setShortcut("Ctrl+Q")
        extractAction.setStatusTip('Leave the Application')
        extractAction.triggered.connect(self.close_application)

        self.ui.menuFile.addAction(extractAction)
        self.ui.btnr.clicked.connect(self.close_application)


    def close_application(self):
        choice = QtWidgets.QMessageBox.question(self, 'Close the Application?', "No Packages will be installed.", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
        if choice == QtWidgets.QMessageBox.Yes:
            QtCore.QCoreApplication.instance().quit()
        else:
            pass

def installProcess():
    global pkglist

    window.ui.btnl.hide()
    window.ui.btnr.setText("&Finish")
    window.ui.progressBar.show()
    window.ui.progressBar.setRange(0,0)
    pkglist = getPackagelistTree()
    installPackages(pkglist)
    #window.ui.progressBar.setRange(0,1)
    #window.ui.progressBar.setValue(1)
    makeDoku(pkglist)
    showSuccBox()

def showSuccBox():
    succBox = QtWidgets.QMessageBox()
    succBox.setText("The selected packages have been installed.")
    succBox.setWindowTitle("Installation Finished!")
    succBox.setIcon(1)
    sys.exit(succBox.exec_())

def showErrorBox():
    errorBox = QtWidgets.QMessageBox()
    errorBox.setText("Something went wrong. No packages have been installed.")
    errorBox.setWindowTitle("Error")
    errorBox.setIcon(3)
    sys.exit(errorBox.exec_())

def showErrorBox(errorstring):
    errorBox = QtWidgets.QMessageBox()
    errorBox.setText(errorstring)
    errorBox.setWindowTitle("Error")
    errorBox.setIcon(3)
    sys.exit(errorBox.exec_())

def chooseFirewall():
    askBox = QtWidgets.QMessageBox()
    askBox.setText("Netzwerk: Soll die Ubuntu Firewall (ufw/gufw) aktiviert werden?")
    askBox.setIcon(4)
    askBox.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
    result = askBox.exec_()
    if result == QtWidgets.QMessageBox.Yes:
        enableFirewall()

def checkIfRoot():
    if os.getuid() != 0:
        errorBox = QtWidgets.QMessageBox()
        errorBox.setText("You must run this script as root.")
        errorBox.setWindowTitle("Please run this script as root.")
        errorBox.setIcon(3)
        sys.exit(errorBox.exec_())
    else:
        pass

def installPackages(strlist):
    global pkglist

    cache.update(sources_list='')
    cache.open(None)

    for pkg in pkglist:
        candidate = cache[pkg]
        if not candidate.is_installed:
            candidate.mark_install()
    try:
        cache.commit(apt.progress.text.AcquireProgress(), apt.progress.base.InstallProgress())
    except Exception as ex:
        print("Error during install",ex)

def enableFirewall():
    command=['ufw', 'enable']
    subprocess_wrap(command)

def mountStick():
    command=[basedir+"/infuse_offline_repo.sh"]
    subprocess_wrap(command)

def makeDoku(stringlist):
    global pkglist

    #command=["echo", "./makeDoku.sh", basedir, " ".join(stringlist)]
    command=["./makeDoku.sh", basedir+"/", " ".join(pkglist)]
    subprocess_wrap(command)

def getPackagelist():
    installList = []
    model = window.ui.tableView.model()
    i = 0
    while i < model.rowCount():
        item = model.item(i)
        item.readOnly(true)
        if item.isEnabled:
            if item.checkState():
                installList.append(item.text())
        i += 1
    return installList

def getPackagelistTree():
    installList = []
    model = window.ui.treeView.model()
    i = 0
    while i < model.rowCount():
        branch = model.item(i)
        j = 0
        #if branch.isEnabled():
            #check if branc is checkt if true return all children true
#            if branch.checkState():
#                while j < branch.rowCount():
#                    installList.append(branch.child(j).text())
#                    j += 1
#            else:
        while j < branch.rowCount():
            if branch.child(j).isEnabled:
                if branch.child(j).checkState():
                    installList.append(branch.child(j).text())
            j += 1
        i += 1
    return installList

def fillTreeView(inputDataJson, treeView):
    model = QtGui.QStandardItemModel()
    branchfont = QtGui.QFont()
    branchfont.setBold(True)
    for softwareGroup in inputDataJson:
        branch = QtGui.QStandardItem(softwareGroup)
        #branch.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
        #branch.setData(QtCore.QVariant(QtCore.Qt.Checked), QtCore.Qt.CheckStateRole)
        branch.setFont(branchfont)
        if 'groupDesc' in inputDataJson[softwareGroup]:
            branchDesc = QtGui.QStandardItem(inputDataJson[softwareGroup]['groupDesc'])
        else:
            branchDesc = QtGui.QStandardItem('')
        for package in inputDataJson[softwareGroup]['packages']:
            if not ('hidden' in package and package['hidden']):
                item = QtGui.QStandardItem(package['pkgname'])
                item.setText(package['pkgname'])
                item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
                if package['tagged']:
                    item.setData(QtCore.QVariant(QtCore.Qt.Checked), QtCore.Qt.CheckStateRole)
                else:
                    item.setData(QtCore.QVariant(QtCore.Qt.Unchecked), QtCore.Qt.CheckStateRole)
                item2 = QtGui.QStandardItem(package['pkgdescription'])
                branch.appendRow([item, item2])
        model.appendRow([branch, branchDesc])
    treeView.setModel(model)
    treeView.expandAll()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    basepath=os.path.realpath(__file__)
    basedir=os.path.dirname(basepath)
    checkIfRoot()
    chooseFirewall()
    mountStick()
    window = Main()
    window.setWindowTitle("Linux Install Party Software Installer")
    with open(basedir+'/../offline_repo.json', 'r') as inputfile:
        data=json.loads(inputfile.read(), object_pairs_hook=OrderedDict)
    fillTreeView(data, window.ui.treeView)
    window.ui.btnl.clicked.connect(installProcess)
    window.show()
    sys.exit(app.exec_())