# -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4
#
# Istanbul - A desktop recorder
# Copyright (C) 2005 Zaheer Abbas Merali (zaheerabbas at merali dot org)
# Copyright (C) 2006 John N. Laliberte (allanonjl@gentoo.org) (jlaliberte@gmail.com)
# Portions Copyright (C) 2004,2005 Fluendo, S.L. (www.fluendo.com).
# All rights reserved.

# This file may be distributed and/or modified under the terms of
# the GNU General Public License version 2 as published by
# the Free Software Foundation.
# This file is distributed without any warranty; without even the implied
# warranty of merchantability or fitness for a particular purpose.
# See "LICENSE.GPL" in the source distribution for more information.

# Headers in this file shall remain intact.

DEBUG=False
import gtk

class Preference(object):
    """
    This class represents a generic preference.
    """
    gconf = None

    def __init__(self, name, type, values, default):
        self.name = name
        self.type = type
        self.valid_values = values
        self.default = default
        self.__value = default

        # if we are the first preference, create the gconf object
        if self.gconf == None and self._has_gconf():
            from istanbul.main.gconf_client import IstanbulGConf
            self.gconf = IstanbulGConf()

        # see if we have this as a stored setting.
        # if we do and its valid, keep it.
        # otherwise, assume the default and set it in gconf.
        if self.gconf != None:
            self.gconf_key = "/apps/istanbul/" + self.name
            temp_val = self.gconf.get_entry(self.name, self.type)
            if self._is_valid(temp_val):
                self.value = temp_val
            else:
                self.gconf.set_entry(self.name, self.value, self.type)
        else:
            self.gconf_key = None

    def _is_valid(self, temp_val):
        if self.type != "integer":
            if temp_val in self.valid_values:
                return True
        else:
            if temp_val >= self.valid_values[0] and temp_val <= self.valid_values[1]:
                return True

        return False

    def generate_gui_event(self, widget, data):
        """
        Return a gui event for this preference.
        """
        if DEBUG: print "generated gui event for: " + self.name
        event = widget.connect("toggled", Preferences().set_preference, "gui", data)
        return event

    def generate_gconf_event(self, widget):
        """
        Return a gconf event for this preference.
        """
        if self.gconf != None:
            if DEBUG: print "generated gconf event for: " + self.name
            event = self.gconf.client.notify_add("/apps/istanbul/" + self.name, Preferences().set_preference, ("gconf", widget))
            return event
        else:
            return None

    def _get_value(self):
        if DEBUG: print "in get value"
        return self.__value

    def _set_value(self, value):
        if DEBUG: print "in set value"
        self.__value = value

        if self.gconf != None:
            # only update if the values aren't equal for some odd reason.
            # we don't want this event firing over and over.
            if self.gconf.get_entry(self.name, self.type) != value:
                self.gconf.set_entry(self.name, self.value, self.type)

    value = property(_get_value, _set_value)

    def _has_gconf(self):
        try:
            import gconf
            return True
        except:
            return False

    def print_i(self):
        print "name: " + str(self.name) + "\n"\
              "type: " + str(self.type)  + "\n"\
              "value: " + str(self.value) + "\n"


class Preferences(object):
    """
    We have a set of default preferences to use if GConf is not available.
    """

    preferences = []
    cached_prefs = {}
    def __init__(self):
        """
        settings are in the following format:
        {<name>:[type, [options], default]
    	"""
        self.settings = {   "video_size":["string", ["full", "half", "quarter"],"full"],
                            "video_framerate":["integer", [1,40], 10],
                            "record_3d":["boolean", [True, False], True],
                            "record_mousepointer":["boolean", [True, False], False],
                            "record_sound":["boolean", [True, False], False]
                            #"encode_later":["boolean", [True, False], False]
                        }

        for setting in self.settings:
            setting_v = self.settings[setting]
            new_pref = Preference(setting, setting_v[0], setting_v[1], setting_v[2])
            self.preferences.append(new_pref)
            if DEBUG: new_pref.print_i()

        self._generate_cached_prefs()

    def _generate_cached_prefs(self):
        for pref in self.preferences:
            self.cached_prefs[pref.name] = pref.value

    def _get_cached_prefs(self):
        """
        Warning, these are read only.  We should enforce this somehow, perhaps convert to tuples.
        Use set_preference to actually set a preference.
        """
        return self.cached_prefs

    Settings = property(_get_cached_prefs)

    def has_gconf(self):
        try:
            import gconf
    	    return True
	    except:
	        return False

    def has_gnomevfs(self):
        try:
            import gnomevfs
            return True
        except:
            return False

    def find_preference(self, name):
        for pref in self.preferences:
            if name == pref.name:
                return pref

        return None

    def set_preference(self, widget, source, *args):
        """
        We assume the widget is named the same as the preference in GConf.

        We have 2 situations.
        1.  We have gconf, so we need to keep in memory and gconf locations the same.
            If we have gconf, we also have to allow updates from gconf to update memory.
        2.  We do not have gconf, so we just work off memory, and settings are lost on exit.
        """

        data = args[-1]
        # this is a normal update from the gui. ( gui already updated )
        # 1.  we update in memory location.
        # 2.  if gconf: we set the new value in gconf. ( done by preference class for us)
        if "gui" == str(source):
            if DEBUG: print "Event from: " + str(source) + " from widget: " + str(widget.get_name())
            preference = self.find_preference(widget.get_name())

            # disconnect events

            if gtk.CheckMenuItem == type(widget):
                preference.value = [False, True][widget.get_active()]
            else:
                print "ERROR: unknown type"

            # reconnect events

        # this is an update from gconf ( gconf already updated )
        # 1.  we update the memory location.
        # 2.  we update the gui.
        # for some reason they put the user args as the last element.
        # -2 is text, last element is Widget class instance
        elif "gconf" == str(data[0]):
            if DEBUG: print "Event from: " + str(args[0].key) + " from gconf."
            # key gives /apps/istanbul/key_name, so lets slice off and get the last element.
            preference = self.find_preference(args[0].key.split("/")[-1])

            # disconnect events, use block and unblock instead.
            data[1].widget.disconnect(data[1].events["gui"])

            preference.value = args[0].value.get_bool()
            data[1].widget.set_active(args[0].value.get_bool())

            # reconnect events
            data[1].events["gui"] = data[1].widget.connect("toggled", Preferences().set_preference, "gui", data)

        else:
            print "ERROR: Unknown event: " + str(source) + str(args) + str(dir(args[0]))
