import os
import sys
import subprocess
import psutil
from Qt import QtCore, QtWidgets
import logging
import utils
import xml.etree.ElementTree as xml_etree
log = logging.getLogger("wizart_desktop")

INTERVAL_IN_MIN = 30
INTERVAL_IN_MS = INTERVAL_IN_MIN * 60 * 1000

TOOL_PATH = os.path.join(os.path.dirname(os.path.dirname(sys.executable)), 'maintenancetool.exe')


class FreelanceSoftwareUpdater(QtCore.QObject):
    def __init__(self, parent=None):
        super(FreelanceSoftwareUpdater, self).__init__(parent)
        self.instance = None
        self.parent = parent
        self.check_updates_timer = QtCore.QTimer()
        self.check_updates_timer.timeout.connect(self.check_updates)
        self.check_updates_timer.setInterval(INTERVAL_IN_MS)
    def __call__(self, *args, **kwargs):
        if self.instance is None:
            self.instance = FreelanceSoftwareUpdater()
        return self.instance

    def run(self):
        self.check_updates_timer.start()

    def check_updates(self):
        p = subprocess.Popen([TOOL_PATH, '--checkupdates'], startupinfo = utils.get_subprocess_startup_info(), stderr = subprocess.STDOUT, stdout = subprocess.PIPE)
        p.wait()
        if p.returncode == 1:
            #this is super strange but if we have no updates, its output "no updates" to 
            log.info("maintenancetool: %s" % p.stdout.read())
        elif p.returncode == 0:
            #try to parse xml output, just silently exit and assume we have No updates 
            try:
                root_node = xml_etree.fromstring(p.stdout.read())
            except:
                pass
            if root_node.tag == "updates": #stdout output wrapped in xml like <updates>..</updates>
                self.show_need_update_popup()
                return True
        else:
            log.error("maintenancetool: %s" % p.stdout.read())
        log.info("maintenancetool exitcode:%d" % p.returncode)
        return False

    def show_need_update_popup(self):
        msg = QtWidgets.QMessageBox(self.parent)
        msg.setIcon(QtWidgets.QMessageBox.Question)
        msg.setText("New updates to Wizart Software available")
        msg.setInformativeText("Do you want to update wizart software now?")
        msg.setWindowTitle("Update window")
        msg.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
        return_value = msg.exec_()
        if return_value == QtWidgets.QMessageBox.Yes:
            self.show_before_apps_closed_dialog()

    def show_not_updates_needed_popup(self):
        msg = QtWidgets.QMessageBox(self.parent)
        msg.setIcon(QtWidgets.QMessageBox.Information)
        msg.setText("No updates available")
        msg.setWindowTitle("Update window")
        msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
        msg.exec_()

    def show_before_apps_closed_dialog(self):
        apps_to_close = self.which_apps_are_running()
        if apps_to_close:
            msg = QtWidgets.QMessageBox(self.parent)
            msg.setIcon(QtWidgets.QMessageBox.Information)
            msg.setText("Following processes should be closed before update:")
            msg.setInformativeText('\n'.join(apps_to_close) + '\n\nPress "Retry" after closing them')
            msg.setWindowTitle("Update window")
            msg.setStandardButtons(QtWidgets.QMessageBox.Retry | QtWidgets.QMessageBox.Cancel)
            return_value = msg.exec_()
            if return_value == QtWidgets.QMessageBox.Retry:
                self.show_before_apps_closed_dialog()
        else:
            self.update_and_reopen()

    def which_apps_are_running(self):
        proc_list = ['maya.exe']
        list_to_close = []
        for proc in psutil.process_iter():
            try:
                if proc.name().lower() in proc_list:
                    list_to_close.append(proc.name().lower())
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                pass
        return list_to_close

    def update_and_reopen(self):
        app = QtWidgets.QApplication.instance()
        app.quit()
        QtCore.QProcess.startDetached(TOOL_PATH, ['--updater'])
