# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import print_function
import os
#import stat
import urllib.request, urllib.error, urllib.parse
from urllib.request import urlopen
from urllib.error import URLError, HTTPError
import zipfile
import tempfile
import shutil
import sys
import platform
from pathlib import Path
from distutils.dir_util import copy_tree
#import webbrowser
import time
from threading import Thread
import contextlib
# entry point to PyMOL's API
from pymol import cmd
# pymol.Qt provides the PyQt5 interface, but may support PyQt4
# and/or PySide as well
from pymol.Qt import QtWidgets, QtCore
from pymol.Qt.utils import loadUi


def __init_plugin__(app=None):
    '''
    Add an entry to the PyMOL "Plugin" menu
    '''
    from pymol.plugins import addmenuitemqt
    addmenuitemqt("ProBiS H2O", lambda: run())

dialog = None

class UpdateCheck:

    def __init__(self):
        self.firstVersionURL = "http://insilab.org/files/probis-h2o/version.txt"
        self.firstArchiveURL = "http://insilab.org/files/probis-h2o/archive.zip"
        self.currentVersion=""
        self.latestVersion =""


    def installationFailed(self):
        global running, status
        status = "failed"
        running = False

    def deleteTmpDir(self):
        try:
            shutil.rmtree(self.tmpDir)
            print(("deleted temporary ", self.tmpDir))
        except:
            print ("error : could not remove temporary directory")
            
    def createTmpDir(self):
        try:
            self.tmpDir= tempfile.mkdtemp()
            print(("created temporary ", self.tmpDir))
        except:
            print ("error : could not create temporary directory")
            self.installationFailed()
        self.zipFileName=os.path.join(self.tmpDir, "archive.zip")

    def downloadInstall(self):
        try:
            print ("Fetching plugin from the git server")
            urlcontent = urlopen(self.firstArchiveURL, timeout=5)
            zipcontent = urlcontent.read()
            H2OzipFile = open(self.zipFileName, 'wb')
            H2OzipFile.write(zipcontent)
        except HTTPError as e1:
            print(("HTTP Error:", e1.code, e1.reason))
            self.installationFailed()
        except URLError as e2:
            print(("URL Error:", e2.reason))
            self.installationFailed()
        except Exception as e:
            print ("Error: download failed, check if http://insilab.org website is up...")
            self.installationFailed()
        finally:
            try:
                H2OzipFile.close()
            except:
                pass
            try:
                urlcontent.close()
            except:
                pass

    def extractInstall(self):
        try:
            with contextlib.closing(zipfile.ZipFile(self.zipFileName, "r")) as H2Ozip:
                for member in H2Ozip.namelist():
                    masterDir = os.path.dirname(member)
                    break
                H2Ozip.extractall(self.tmpDir)
            # copy new
            copy_tree(os.path.join(self.tmpDir, masterDir, ".probisH2O"), H2O_DIRECTORY)
        except:
            print ("installation of probis H2O failed")
            self.installationFailed()

    def firstUpgrade(self):
        return not os.path.isdir(H2O_DIRECTORY)

    def upgrade(self):
        
        self.createTmpDir()
        self.downloadInstall()
        self.extractInstall()
        self.deleteTmpDir()
        sys.path.append(os.path.normpath(os.path.join(H2O_DIRECTORY, "module")))
        self.findLatestVersion()
        self.writeToVersionTxt(self.latestVersion)

        print ("Upgrade finished successfully!")
        global running, status
        status = "start"
        running = False
        
    def findCurrentVersion(self):
        if os.path.isfile(versionFile):
            with open(versionFile, 'r') as myFile:
                global currentVersion
                lines = myFile.readlines()
                self.currentVersion = lines[0].strip()
                currentVersion = self.currentVersion

    def findLatestVersion(self):
        try:
            global latestVersion
            versionFile = urllib.request.urlopen(self.firstVersionURL, timeout=5)
            self.latestVersion = versionFile.read().decode(encoding="utf-8").strip()
            if len(self.latestVersion) > 6:
                self.latestVersion = ""
            latestVersion = self.latestVersion
            
        except HTTPError as e1:
            print(("HTTP Error:", e1.code, e1.reason))
        except URLError as e2:
            print(("URL Error:", e2.reason))
        except Exception as e:
            print ("URL Error: Is Insilab webpage (http://insilab.org) down?")

    
    def writeToVersionTxt(version, reminder=False):
        if reminder:
            with open(versionFile, 'a') as myfile:
                myfile.write(str(version)+"\t later \t"+time.strftime("%d/%m/%Y")+"\n")
        else:
            with open(versionFile, 'w') as myfile:
                #myfile.write(str(version)+"\n".encode("ascii"))
                myfile.write((str(version)+"\n").encode("ascii"))
    def updateBox(self):
        global updateDialog

        updateDialog = self.updateWindow()

        updateDialog.show()
    
    def updateWindow(self):
        global updateDialog
        updateDialog = QtWidgets.QMainWindow()

        uifile = os.path.join(UI_DIRECTORY, 'GUIupdate.ui')
        form = loadUi(uifile, updateDialog)

        def cancelButton():
            global status
            if form.checkBoxAsk.isChecked():
                self.writeToVersionTxt(self.latestVersion, True)
            updateDialog.close()
            start_probis_h2o()
            

        def updateButton(vent=None):
            global status
            updateDialog.close()
            self.upgrade()
            updateDialog.close()
            start_probis_h2o()
            
        self.findLatestVersion()
        self.findCurrentVersion()
    
        form.labelVersionLatest.setText(str(self.latestVersion))
        form.labelVersionCurrent.setText(str(self.currentVersion))
        form.buttonBoxUpdate.accepted.connect(lambda: updateButton())
        form.buttonBoxUpdate.rejected.connect(lambda: cancelButton())
    
        return updateDialog
def internetOn():
        try:
            urllib.request.urlopen('http://insilab.org',timeout=5)
            return True
        except:
            return False

def msgButtonClick(i):
   print("Button clicked is:",i.text())
   
def showManualDlInfo():
    msgBox = QtWidgets.QMessageBox()
    msgBox.setIcon(QtWidgets.QMessageBox.Information)
    msgBox.setText("Installation failed: To download and manually install Probis H2O please visit our website http://www.insilab.org/probis-h2o/ .")
    msgBox.setWindowTitle("Instalation error message")
    msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel)
    msgBox.buttonClicked.connect(msgButtonClick)   

def start_probis_h2o():
    print(("Python version: "+platform.architecture()[0]))
    sys.path.append(os.path.normpath(os.path.join(H2O_DIRECTORY, "module")))
    import ProBiS_H2O_plugin
    ProBiS_H2O_plugin.main()

class CustomDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setWindowTitle("Choose Directory")
    def find_dir(self):
        folderpath = str(QtWidgets.QFileDialog.getExistingDirectory(CustomDialog(), "Select Directory"))
        if folderpath.endswith(".probisH2O") or folderpath.endswith(".probisH2O"+os.path.sep):
            pass
        else:
            folderpath=os.path.join(folderpath, ".probisH2O")
        self.lineEdit.setText(folderpath)
    def set_dir(self):
        global SetDir
        SetDir = self.lineEdit.text()   
        install_datoteka = open(install_dir, "w")
        install_datoteka.write(SetDir)
        install_datoteka.close()
        InstallDialog.close()
            
    def setupUI(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(640, 148)
        Dialog.setMaximumSize(QtCore.QSize(16777215, 210))
        self.gridLayout = QtWidgets.QGridLayout(Dialog)
        self.gridLayout.setObjectName("gridLayout")
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 0, 0, 1, 2)
        self.lineEdit = QtWidgets.QLineEdit(Dialog)
        self.lineEdit.setObjectName("lineEdit")
        self.gridLayout.addWidget(self.lineEdit, 1, 0, 1, 1)
        HOME_DIRECTORY=os.path.expanduser('~')
        DEFAULT_DIRECTORY=os.path.join(HOME_DIRECTORY, ".probisH2O")
        self.lineEdit.setText(DEFAULT_DIRECTORY)
        self.pushButton = QtWidgets.QPushButton(Dialog)
        self.pushButton.setObjectName("pushButton")
        self.gridLayout.addWidget(self.pushButton, 1, 1, 1, 1)
        self.pushButton.clicked.connect(self.find_dir)
        self.label_2 = QtWidgets.QLabel(Dialog)
        self.label_2.setObjectName("label_2")
        self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
        self.pushOK = QtWidgets.QPushButton(Dialog)
        self.pushOK.setObjectName("pushOK")
        self.gridLayout.addWidget(self.pushOK, 3, 1, 1, 1)
        self.pushOK.clicked.connect(self.set_dir)
        

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)
        
    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        self.label.setText(_translate("Dialog", "Please choose install directory for ProBiS H2O:"))
        self.pushButton.setText(_translate("Dialog", "Pick directory"))
        self.label_2.setText(_translate("Dialog", "*If ProBiS H2O has been manually installed please input .probisH2O file."))
        self.pushOK.setText(_translate("Dialog", "OK"))

def run_custom_dialog():
    global InstallDialog
    InstallDialog=QtWidgets.QDialog()
    InstallDialog.ui = CustomDialog()
    InstallDialog.ui.setupUI(InstallDialog)
    InstallDialog.show()
    InstallDialog.exec_()

def NoInstallSetting():
    global SetDir
    run_custom_dialog()
    if not SetDir=="":
        install_datoteka = open(install_dir, "w")
        install_datoteka.write(SetDir)
        install_datoteka.close()
    else:
        QtWidgets.QMessageBox.about(dialog, "ProBiS H2O Install Warning", "Please choose an install directory!")
        print("Please choose an install directory!")
    
def run():
    global H2O_DIRECTORY, UI_DIRECTORY, versionFile, install_dir
    install_dir=os.path.join(Path.home(), ".probish2o_installdir.txt")
            
    if os.path.isfile(install_dir) == True:
        install_datoteka = open(install_dir, "r")
        if os.path.isdir(install_datoteka.readline()):
            install_datoteka.close()
        else:
            install_datoteka.close()
            os.remove(install_dir)

    try:
        if os.path.isfile(install_dir) == False:
            NoInstallSetting()        
        install_datoteka = open(install_dir, "r")
        H2O_DIRECTORY=install_datoteka.readline()
        install_datoteka.close()
        UI_DIRECTORY=os.path.join(H2O_DIRECTORY,"UI")
        versionFile = os.path.join(H2O_DIRECTORY, "version.txt")
    except:
        if os.path.exists(install_dir):
            os.remove(install_dir)
        QtWidgets.QMessageBox.about(dialog, "ProBiS H2O Install Warning", "Something went wrong!\nPlease choose an install directory!")
        print("Something went wrong!\nPlease choose an install directory!")


    print("Initialising Probis H2O ...")

    global running, status
    status = "start"

    try:
        sys.path.remove('')
    except:
        pass

    if UpdateCheck().firstUpgrade():
        print("First time installation...")
        if not internetOn():
            status = "no-internet"
        else:
            UpdateCheck().findLatestVersion()
            UpdateCheck().upgrade()
    else:
        UpdateCheck().findCurrentVersion()
        print("Not First time installation")
        if internetOn() == True:
            UpdateCheck().findLatestVersion()
            if str(latestVersion) != str(currentVersion):
                print("Update Needed!")
                status = "check-update"
    
    running = False
    main()
# ----------------------------------------------------THREADING-----------------        
class FuncThread(Thread):
    def __init__(self, target, *args):
      Thread.__init__(self)
      self._target = target
      self._args = args
      print( self._args )

    def run(self, *args):
      print( self._args )
      self._target(*self._args)
     
def main():
    global status
    if status == "no-internet":
        print("There is no internet or the website http://insilab.org is unreachable. Internet should be turned on during installation.")
        msgBox = QtWidgets.QMessageBox()
        msgBox.setIcon(QtWidgets.QMessageBox.Information)
        msgBox.setText("Communication Error: No Internet connection available. Please make sure that your device is connected to the Internet.")
        msgBox.setWindowTitle("Communication error message")
        msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel)
        msgBox.buttonClicked.connect(msgButtonClick)   

    if status == "check-update":
        print("Check update")
        UpdateCheck().updateBox()

    if status == "start":
        print("Starting ProBiS H2O")
        start_probis_h2o()

    else:
        print("Manual installation info")
        showManualDlInfo()