import sys, os, subprocess, re
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GdkPixbuf, GLib
import gettext

try:
    from ConfigParser import ConfigParser as ConfigParser
except:
    from configparser import ConfigParser as ConfigParser

nebula_dir = sys.path[0]
app_icon = GdkPixbuf.Pixbuf.new_from_file(nebula_dir + '/images/icon.png')

gettext.bindtextdomain('games_nebula', nebula_dir + '/locale')
gettext.textdomain('games_nebula')
_ = gettext.gettext

class GUI:

    def __init__(self):
        self.n_files_to_copy = 0
        self.config_load()
        self.create_main_window()

    def config_load(self):

        global_config_file = os.getenv('HOME') + '/.games_nebula/config/config.ini'
        global_config_parser = ConfigParser()
        global_config_parser.read(global_config_file)

        gtk_theme = global_config_parser.get('visuals', 'gtk_theme')
        gtk_dark = global_config_parser.getboolean('visuals', 'gtk_dark')
        icon_theme = global_config_parser.get('visuals', 'icon_theme')
        font = global_config_parser.get('visuals','font')
        screen = Gdk.Screen.get_default()
        gsettings = Gtk.Settings.get_for_screen(screen)
        gsettings.set_property('gtk-theme-name', gtk_theme)
        gsettings.set_property('gtk-application-prefer-dark-theme', gtk_dark)
        gsettings.set_property('gtk-icon-theme-name', icon_theme)
        gsettings.set_property('gtk-font-name', font)

        if not global_config_parser.has_section('goglib preferences'):
            global_config_parser.add_section('goglib preferences')

        if not global_config_parser.has_option('goglib preferences', 'goglib_download_dir'):
            goglib_download_dir = os.getenv('HOME') + '/.games_nebula/games/goglib/downloads'
            global_config_parser.set('goglib preferences', 'goglib_download_dir', str(goglib_download_dir))
        else:
            goglib_download_dir = global_config_parser.get('goglib preferences', 'goglib_download_dir')

        if not global_config_parser.has_section('emulation settings'):
            global_config_parser.add_section('emulation settings')

        if not global_config_parser.has_option('emulation settings', 'winetricks_cache'):
            self.winetricks_cache = os.getenv('HOME') + '/.cache/winetricks'
            global_config_parser.set('emulation settings', 'winetricks_cache', str(self.winetricks_cache))
        else:
            self.winetricks_cache = global_config_parser.get('emulation settings', 'winetricks_cache')

        if not global_config_parser.has_option('emulation settings', 'winetricks_cache_backup'):
            self.winetricks_cache_backup = goglib_download_dir + '/_winetricks_cache_backup'
            global_config_parser.set('emulation settings', 'winetricks_cache_backup', str(self.winetricks_cache_backup))
        else:
            self.winetricks_cache_backup = global_config_parser.get('emulation settings', 'winetricks_cache_backup')

        if not os.path.exists(self.winetricks_cache):
            os.makedirs(self.winetricks_cache)

        if not os.path.exists(self.winetricks_cache_backup):
            os.makedirs(self.winetricks_cache_backup)

        config_file = open(os.getenv('HOME') + '/.games_nebula/config/config.ini', 'w')
        global_config_parser.write(config_file)
        config_file.close()

    def config_save(self):

        config_file = os.getenv('HOME') + '/.games_nebula/config/config.ini'
        config_parser = ConfigParser()
        config_parser.read(config_file)

        config_parser.set('emulation settings', 'winetricks_cache', str(self.winetricks_cache))
        config_parser.set('emulation settings', 'winetricks_cache_backup', str(self.winetricks_cache_backup))

        new_config_file = open(os.getenv('HOME') + '/.games_nebula/config/config.ini', 'w')
        config_parser.write(new_config_file)
        new_config_file.close()

    def create_main_window(self):

        self.main_window = Gtk.Window(
            title = "Games Nebula",
            type = Gtk.WindowType.TOPLEVEL,
            window_position = Gtk.WindowPosition.CENTER_ALWAYS,
            resizable = False,
            icon = app_icon,
            #width_request = 180,
            #height_request = 240
            )

        self.main_window.connect('delete-event', Gtk.main_quit)

        grid = Gtk.Grid(
            margin_top = 10,
            margin_bottom = 10,
            margin_left = 10,
            margin_right = 10,
            row_spacing = 10,
            column_spacing = 10
            )

        label_cache = Gtk.Label(
            label = _("Winetricks cache")
            )

        filechooserbutton_cache = Gtk.FileChooserButton(
            title = _("Winetricks cache"),
            action =  Gtk.FileChooserAction.SELECT_FOLDER,
            )
        filechooserbutton_cache.set_current_folder(self.winetricks_cache)
        filechooserbutton_cache.connect('file-set', self.cb_filechooserbutton_cache)

        label_cache_backup = Gtk.Label(
            label = _("Winetricks cache backup")
            )

        filechooserbutton_cache_backup = Gtk.FileChooserButton(
            title = _("Winetricks cache backup"),
            action =  Gtk.FileChooserAction.SELECT_FOLDER,
            )
        filechooserbutton_cache_backup.set_current_folder(self.winetricks_cache_backup)
        filechooserbutton_cache_backup.connect('file-set', self.cb_filechooserbutton_cache_backup)

        self.button_make_backup = Gtk.Button(
            label = _("Make backup")
            )
        self.button_make_backup.connect('clicked', self.cb_button_make_backup)

        self.button_restore_backup = Gtk.Button(
            label = _("Restore from backup")
            )
        self.button_restore_backup.connect('clicked', self.cb_button_restore_backup)

        self.progressbar = Gtk.ProgressBar(
            hexpand = True,
            show_text = True,
            text = _("Processing..."),
            pulse_step = 0.1,
            no_show_all = True
            )

        grid.attach(label_cache, 0, 0, 1, 1)
        grid.attach(filechooserbutton_cache, 1, 0, 1, 1)
        grid.attach(label_cache_backup, 0, 1, 1, 1)
        grid.attach(filechooserbutton_cache_backup, 1, 1, 1, 1)
        grid.attach(self.button_make_backup, 0, 2, 2, 1)
        grid.attach(self.button_restore_backup, 0, 3, 2, 1)
        grid.attach(self.progressbar, 0, 4, 2, 1)

        self.main_window.add(grid)

        self.main_window.show_all()

    def cb_filechooserbutton_cache(self, filechooserbutton):
        self.winetricks_cache = filechooserbutton.get_filename()

    def cb_filechooserbutton_cache_backup(self, filechooserbutton):
        self.winetricks_cache_backup = filechooserbutton.get_filename()

    def cb_button_make_backup(self, button):

        self.config_save()

        files_cache = os.listdir(self.winetricks_cache)
        files_backup = os.listdir(self.winetricks_cache_backup)

        files_to_copy = list(set(files_cache) - set(files_backup))
        self.n_files_to_copy = len(files_to_copy)

        if self.n_files_to_copy == 0:

            message_dialog = Gtk.MessageDialog(
                self.main_window,
                0,
                Gtk.MessageType.ERROR,
                Gtk.ButtonsType.OK,
                _("Backup is up to date"),
                width_request = 360
                )
            content_area = message_dialog.get_content_area()
            content_area.set_property('margin-left', 10)
            content_area.set_property('margin-right', 10)
            content_area.set_property('margin-top', 10)
            content_area.set_property('margin-bottom', 10)
            action_area = message_dialog.get_action_area()
            action_area.set_property('spacing', 10)

            self.main_window.hide()
            message_dialog.run()
            message_dialog.destroy()
            self.main_window.show()

        else:

            self.button_make_backup.set_visible(False)
            self.button_restore_backup.set_visible(False)
            self.progressbar.set_visible(True)

            for file_name in files_to_copy:
                self.copy_files(file_name, 'make_backup')

    def cb_button_restore_backup(self, button):

        self.config_save()

        files_cache = os.listdir(self.winetricks_cache)
        files_backup = os.listdir(self.winetricks_cache_backup)

        files_to_copy = list(set(files_backup) - set(files_cache))
        self.n_files_to_copy = len(files_to_copy)

        if self.n_files_to_copy == 0:

            message_dialog = Gtk.MessageDialog(
                self.main_window,
                0,
                Gtk.MessageType.ERROR,
                Gtk.ButtonsType.OK,
                _("All files from backup exists in cache"),
                width_request = 360
                )
            content_area = message_dialog.get_content_area()
            content_area.set_property('margin-left', 10)
            content_area.set_property('margin-right', 10)
            content_area.set_property('margin-top', 10)
            content_area.set_property('margin-bottom', 10)
            action_area = message_dialog.get_action_area()
            action_area.set_property('spacing', 10)

            self.main_window.hide()
            message_dialog.run()
            message_dialog.destroy()
            self.main_window.show()

        else:

            self.button_make_backup.set_visible(False)
            self.button_restore_backup.set_visible(False)
            self.progressbar.set_visible(True)

            for file_name in files_to_copy:
                self.copy_files(file_name, 'restore_backup')

    def copy_files(self, file_name, action):

        if action == 'make_backup':
            command = ['cp', '-R', self.winetricks_cache + '/' + file_name, self.winetricks_cache_backup]
        elif action == 'restore_backup':
            command = ['cp', '-R', self.winetricks_cache_backup + '/' + file_name, self.winetricks_cache]

        self.pid, stdin, stdout, stderr = GLib.spawn_async(command,
                                    flags=GLib.SpawnFlags.SEARCH_PATH|GLib.SpawnFlags.DO_NOT_REAP_CHILD,
                                    standard_output=True,
                                    standard_error=True)

        io = GLib.IOChannel(stdout)

        self.source_id_out = io.add_watch(GLib.IO_IN|GLib.IO_HUP,
                             self.watch_process,
                             'copy_files',
                             priority=GLib.PRIORITY_HIGH)

    def watch_process(self, io, condition, process_name):

        if condition is GLib.IO_HUP:

            self.progressbar.pulse()

            self.n_files_to_copy -= 1

            if self.n_files_to_copy == 0:

                message_dialog = Gtk.MessageDialog(
                    self.main_window,
                    0,
                    Gtk.MessageType.ERROR,
                    Gtk.ButtonsType.OK,
                    _("Done!"),
                    width_request = 360
                    )
                content_area = message_dialog.get_content_area()
                content_area.set_property('margin-left', 10)
                content_area.set_property('margin-right', 10)
                content_area.set_property('margin-top', 10)
                content_area.set_property('margin-bottom', 10)
                action_area = message_dialog.get_action_area()
                action_area.set_property('spacing', 10)

                self.main_window.hide()
                message_dialog.run()
                message_dialog.destroy()

                Gtk.main_quit()

            return False

        while Gtk.events_pending():
            Gtk.main_iteration_do(False)

        return True

def main():
    import sys
    app = GUI()
    Gtk.main()

if __name__ == '__main__':
    sys.exit(main())