
# Copyright (c) 2011 Loïc Faure-Lacroix


import os.path
import shutil
import zipfile
import tempfile

import os

from gi.repository import Gtk
from gi.repository import GLib

from gtweak.gsettings import GSettingsSetting
from gtweak.gshellwrapper import GnomeShell
from gtweak.tweakmodel import Tweak, TweakGroup
from gtweak.widgets import GConfComboTweak, GSettingsComboEnumTweak, GSettingsSwitchTweak, build_label_beside_widget, build_horizontal_sizegroup

disabled_path = os.path.join(GnomeShell.DATA_DIR, 'extensions.disabled')
extensions_path = os.path.join(GnomeShell.DATA_DIR, 'extensions')

class Switcher(Gtk.Switch):
    
    def __init__(self, extension):
        Gtk.Switch.__init__(self)
        self.connect('notify::active', self.toggled)
        self.extension = extension

    def toggled(self, btn, data):
        if os.path.exists(os.path.join(extensions_path, self.extension)) and btn.get_active():
            pass
        elif os.path.exists(os.path.join(extensions_path, self.extension)) and not btn.get_active():
            os.remove(os.path.join(extensions_path, self.extension))
        elif btn.get_active():
            os.symlink(os.path.join(disabled_path, self.extension),
                       os.path.join(extensions_path, self.extension))


class ExtensionsSelector(Tweak):
    def __init__(self, **options):

        Tweak.__init__(self, "Shell extensions", "Install custom or user extensions for gnome-shell", **options)
        
        error = "Unknown"
        
        try:
            self._shell = GnomeShell()
        except:
            error = "Shell not running"
        try:
            error = None
        except Exception, e:
            error = "Could not list shell extensions"

        self.name = "extensions"

        if error:
            info = Gtk.InfoBar()
            info.props.message_type = Gtk.MessageType.INFO
            info.get_content_area().add(Gtk.Label(error))
            self.widget = build_label_beside_widget(self.name, info)
            self.widget_for_size_group = info
        else:
            self._clean()
            self.hb = Gtk.VBox()
            chooser = _ThemeZipChooser()
            chooser.connect("file-set", self._on_file_set)
            self.hb.pack_start(chooser, False, False, 0)
            self.hb.pack_start(Gtk.Label('Available extensions'), False, False, 5)
            # Load extensions
            activated = self.__get_extensions(extensions_path)
            self.__load_extensions(self.hb, activated.items(), True)
            # Load disabled extensions
            available = self.__get_extensions(disabled_path)

            for key in activated.keys():
                del available[key] 

            self.__load_extensions(self.hb, available.items(), False)
            self.widget = self.hb
            self.widget_for_size_group = self.hb

    def __get_extensions(self, directory):

        extensions = {}

        if not os.path.exists(directory):
            os.mkdir(disabled_path)

        for dirn in os.listdir(directory):
            extension = os.path.join(directory, dirn)
            try:
            	metadata_file = open(os.path.join(extension, 'metadata.json'))
                metadata = eval(metadata_file.read())
                extensions[dirn] = metadata
            except:
                pass

        return extensions

    def __load_extensions(self, container, values, active):
        for k, v in values:
            w = Switcher(k)
            if active:
                w.set_active(True)
            widget = build_label_beside_widget(v.get('name'), w)
            container.pack_start(widget, False, False, 5)

    def _activate_deactivate(self, btn):
        print "clicked"
                   
    def _on_file_set(self, chooser):
        f = chooser.get_filename()

        with zipfile.ZipFile(f, 'r') as z:
            try:
                #check this looks like a valid theme
                metadata_file = z.open('metadata.json')
                metadata = eval(metadata_file.read()) 
                uuid = metadata.get('uuid')

                self._extract_theme_zip(z, uuid)

		self.__load_extensions(self.hb, {uuid: metadata}.items())
            except KeyError:
                #does not look like a valid theme
                self.notify_error("Invalid extension file")
        #set button back to default state
        chooser.unselect_all()

    def _extract_theme_zip(self, z, extension_uuid):
        tmp = tempfile.mkdtemp()
        dest = os.path.join(disabled_path, extension_uuid)
        try:
            if os.path.exists(dest):
                shutil.rmtree(dest)
            z.extractall(tmp)
            shutil.copytree(tmp, dest)
        except OSError:
            self.notify_error("Error installing theme")

    def _clean(self):
        print "cleaning"
	for dirn in os.listdir(extensions_path):
            origin = os.path.join(extensions_path, dirn)
            target = os.path.join(disabled_path, dirn)
            if not os.path.islink(origin) and not os.path.exists(target):
                os.rename(origin, target)
                os.symlink(target, origin)


class _ThemeZipChooser(Gtk.FileChooserButton):
    def __init__(self):
        Gtk.FileChooserButton.__init__(self, title="Select theme file")

        f = Gtk.FileFilter()
        f.add_mime_type("application/zip")
        self.set_filter(f)

        #self.set_width_chars(15)
        self.set_local_only(True)

sg = build_horizontal_sizegroup()

TWEAK_GROUPS = (
        TweakGroup(
            "Extensions",
            ExtensionsSelector(size_group=sg),
	),
)
