/**
 * gpm_settings_key_changed_cb:
 *
 * We might have to do things when the keys change; do them here.
 **/
static void
gpm_settings_key_changed_cb (GSettings *settings, const gchar *key, GpmBacklight *backlight)
{
    gboolean on_battery;

    /* get battery status */
    g_object_get (backlight->priv->client,
                  "on-battery", &on_battery,
                  NULL);

    if (!on_battery && g_strcmp0 (key, GPM_SETTINGS_BRIGHTNESS_AC) == 0) {
        backlight->priv->master_percentage = g_settings_get_double (settings, key);
        gpm_backlight_brightness_evaluate_and_set (backlight, FALSE, TRUE);

    } else if (on_battery && g_strcmp0 (key, GPM_SETTINGS_BRIGHTNESS_DIM_BATT) == 0) {
        gpm_backlight_brightness_evaluate_and_set (backlight, FALSE, TRUE);

    } else if (g_strcmp0 (key, GPM_SETTINGS_IDLE_DIM_AC) == 0 ||
               g_strcmp0 (key, GPM_SETTINGS_BACKLIGHT_ENABLE) == 0 ||
               g_strcmp0 (key, GPM_SETTINGS_SLEEP_DISPLAY_BATT) == 0 ||
               g_strcmp0 (key, GPM_SETTINGS_BACKLIGHT_BATTERY_REDUCE) == 0 ||
               g_strcmp0 (key, GPM_SETTINGS_IDLE_BRIGHTNESS) == 0) {
        gpm_backlight_brightness_evaluate_and_set (backlight, FALSE, TRUE);

    } else if (g_strcmp0 (key, GPM_SETTINGS_IDLE_DIM_TIME) == 0) {
        backlight->priv->idle_dim_timeout = g_settings_get_int (settings, key);
        gpm_idle_set_timeout_dim (backlight->priv->idle, backlight->priv->idle_dim_timeout);
    } else {
        egg_debug ("unknown key %s", key);
    }
}
/**
 * gpm_backlight_button_pressed_cb:
 * @power: The power class instance
 * @type: The button type, e.g. "power"
 * @state: The state, where TRUE is depressed or closed
 * @brightness: This class instance
 **/
static void
gpm_backlight_button_pressed_cb (GpmButton *button, const gchar *type, GpmBacklight *backlight)
{
	gboolean ret;
	GError *error = NULL;
	guint percentage;
	gboolean hw_changed;
	egg_debug ("Button press event type=%s", type);

	if (strcmp (type, GPM_BUTTON_BRIGHT_UP) == 0) {
		/* go up one step */
		ret = gpm_brightness_up (backlight->priv->brightness, &hw_changed);

		/* show the new value */
		if (ret) {
			gpm_brightness_get (backlight->priv->brightness, &percentage);
			gpm_backlight_dialog_init (backlight);
			gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (backlight->priv->popup),
								percentage);
			gpm_backlight_dialog_show (backlight);
			/* save the new percentage */
			backlight->priv->master_percentage = percentage;
		}
		/* we emit a signal for the brightness applet */
		if (ret && hw_changed) {
			egg_debug ("emitting brightness-changed : %i", percentage);
			g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, percentage);
		}
	} else if (strcmp (type, GPM_BUTTON_BRIGHT_DOWN) == 0) {
		/* go up down step */
		ret = gpm_brightness_down (backlight->priv->brightness, &hw_changed);

		/* show the new value */
		if (ret) {
			gpm_brightness_get (backlight->priv->brightness, &percentage);
			gpm_backlight_dialog_init (backlight);
			gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (backlight->priv->popup),
								percentage);
			gpm_backlight_dialog_show (backlight);
			/* save the new percentage */
			backlight->priv->master_percentage = percentage;
		}
		/* we emit a signal for the brightness applet */
		if (ret && hw_changed) {
			egg_debug ("emitting brightness-changed : %i", percentage);
			g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, percentage);
		}
	} else if (strcmp (type, GPM_BUTTON_LID_OPEN) == 0) {
		/* make sure we undim when we lift the lid */
		gpm_backlight_brightness_evaluate_and_set (backlight, FALSE);

		/* ensure backlight is on */
		ret = gpm_dpms_set_mode (backlight->priv->dpms, GPM_DPMS_MODE_ON, &error);
		if (!ret) {
			egg_warning ("failed to turn on DPMS: %s", error->message);
			g_error_free (error);
		}
	}
}
/**
 * gpm_conf_gconf_key_changed_cb:
 *
 * We might have to do things when the gconf keys change; do them here.
 **/
static void
gpm_conf_gconf_key_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, GpmBacklight *backlight)
{
	GConfValue *value;
	gboolean on_battery;

	value = gconf_entry_get_value (entry);
	if (value == NULL)
		return;

	/* get battery status */
	g_object_get (backlight->priv->client,
		      "on-battery", &on_battery,
		      NULL);

	if (!on_battery && strcmp (entry->key, GPM_CONF_BACKLIGHT_BRIGHTNESS_AC) == 0) {
		backlight->priv->master_percentage = gconf_value_get_int (value);
		gpm_backlight_brightness_evaluate_and_set (backlight, FALSE);

	} else if (on_battery && strcmp (entry->key, GPM_CONF_BACKLIGHT_BRIGHTNESS_DIM_BATT) == 0) {
		gpm_backlight_brightness_evaluate_and_set (backlight, FALSE);

	} else if (strcmp (entry->key, GPM_CONF_BACKLIGHT_IDLE_DIM_AC) == 0 ||
	         strcmp (entry->key, GPM_CONF_BACKLIGHT_ENABLE) == 0 ||
	         strcmp (entry->key, GPM_CONF_TIMEOUT_SLEEP_DISPLAY_BATT) == 0 ||
	         strcmp (entry->key, GPM_CONF_BACKLIGHT_BATTERY_REDUCE) == 0 ||
	         strcmp (entry->key, GPM_CONF_BACKLIGHT_IDLE_BRIGHTNESS) == 0) {
		gpm_backlight_brightness_evaluate_and_set (backlight, FALSE);

	} else if (strcmp (entry->key, GPM_CONF_BACKLIGHT_IDLE_DIM_TIME) == 0) {
		backlight->priv->idle_dim_timeout = gconf_value_get_int (value);
		gpm_idle_set_timeout_dim (backlight->priv->idle, backlight->priv->idle_dim_timeout);
	} else {
		egg_debug ("unknown key %s", entry->key);
	}
}
/**
 * gpm_backlight_init:
 * @brightness: This brightness class instance
 *
 * initialises the brightness class. NOTE: We expect laptop_panel objects
 * to *NOT* be removed or added during the session.
 * We only control the first laptop_panel object if there are more than one.
 **/
static void
gpm_backlight_init (GpmBacklight *backlight)
{
	gboolean lid_is_present = TRUE;
	GpmPrefsServer *prefs_server;

	backlight->priv = GPM_BACKLIGHT_GET_PRIVATE (backlight);

	/* record our idle time */
	backlight->priv->idle_timer = g_timer_new ();

	/* watch for manual brightness changes (for the popup widget) */
	backlight->priv->brightness = gpm_brightness_new ();
	g_signal_connect (backlight->priv->brightness, "brightness-changed",
			  G_CALLBACK (brightness_changed_cb), backlight);

	/* we use up_client for the ac-adapter-changed signal */
	backlight->priv->client = up_client_new ();
	g_signal_connect (backlight->priv->client, "changed",
			  G_CALLBACK (gpm_backlight_client_changed_cb), backlight);

	/* gets caps */
	backlight->priv->can_dim = gpm_brightness_has_hw (backlight->priv->brightness);

	/* we use DeviceKit-power to see if we should show the lid UI */
	g_object_get (backlight->priv->client,
		      "lid-is-present", &lid_is_present,
		      NULL);

	/* expose ui in prefs program */
	prefs_server = gpm_prefs_server_new ();
	if (lid_is_present)
		gpm_prefs_server_set_capability (prefs_server, GPM_PREFS_SERVER_LID);
	if (backlight->priv->can_dim)
		gpm_prefs_server_set_capability (prefs_server, GPM_PREFS_SERVER_BACKLIGHT);
	g_object_unref (prefs_server);

	/* watch for dim value changes */
	backlight->priv->conf = gconf_client_get_default ();

	/* watch gnome-power-manager keys */
	gconf_client_add_dir (backlight->priv->conf, GPM_CONF_DIR, GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
	gconf_client_notify_add (backlight->priv->conf, GPM_CONF_DIR,
				 (GConfClientNotifyFunc) gpm_conf_gconf_key_changed_cb,
				 backlight, NULL, NULL);

	/* set the main brightness, this is designed to be updated if the user changes the
	 * brightness so we can undim to the 'correct' value */
	backlight->priv->master_percentage = gconf_client_get_int (backlight->priv->conf, GPM_CONF_BACKLIGHT_BRIGHTNESS_AC, NULL);

	/* watch for brightness up and down buttons and also check lid state */
	backlight->priv->button = gpm_button_new ();
	g_signal_connect (backlight->priv->button, "button-pressed",
			  G_CALLBACK (gpm_backlight_button_pressed_cb), backlight);

	/* watch for idle mode changes */
	backlight->priv->idle = gpm_idle_new ();
	g_signal_connect (backlight->priv->idle, "idle-changed",
			  G_CALLBACK (idle_changed_cb), backlight);

	/* assumption */
	backlight->priv->system_is_idle = FALSE;
	backlight->priv->idle_dim_timeout = gconf_client_get_int (backlight->priv->conf, GPM_CONF_BACKLIGHT_IDLE_DIM_TIME, NULL);
	gpm_idle_set_timeout_dim (backlight->priv->idle, backlight->priv->idle_dim_timeout);

	/* use a visual widget */
	backlight->priv->popup = gsd_media_keys_window_new ();
	gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (backlight->priv->popup),
						 "gpm-brightness-lcd",
						 TRUE);
        gtk_window_set_position (GTK_WINDOW (backlight->priv->popup), GTK_WIN_POS_NONE);

	/* DPMS mode poll class */
	backlight->priv->dpms = gpm_dpms_new ();

	/* we refresh DPMS on resume */
	backlight->priv->control = gpm_control_new ();
	g_signal_connect (backlight->priv->control, "resume",
			  G_CALLBACK (control_resume_cb), backlight);

	/* Don't do dimming on inactive console */
	backlight->priv->consolekit = egg_console_kit_new ();

	/* sync at startup */
	gpm_backlight_brightness_evaluate_and_set (backlight, FALSE);
}
/**
 * idle_changed_cb:
 * @idle: The idle class instance
 * @mode: The idle mode, e.g. GPM_IDLE_MODE_BLANK
 * @manager: This class instance
 *
 * This callback is called when gnome-screensaver detects that the idle state
 * has changed. GPM_IDLE_MODE_BLANK is when the session has become inactive,
 * and GPM_IDLE_MODE_SLEEP is where the session has become inactive, AND the
 * session timeout has elapsed for the idle action.
 **/
static void
idle_changed_cb (GpmIdle *idle, GpmIdleMode mode, GpmBacklight *backlight)
{
	gboolean ret;
	GError *error = NULL;
	gboolean on_battery;
	gchar *dpms_method;
	GpmDpmsMode dpms_mode;

	/* don't dim or undim the screen when the lid is closed */
	if (gpm_button_is_lid_closed (backlight->priv->button))
		return;

	/* don't dim or undim the screen unless we are on the active console */
	if (!egg_console_kit_is_active (backlight->priv->consolekit)) {
		egg_debug ("ignoring as not on active console");
		return;
	}

	if (mode == GPM_IDLE_MODE_NORMAL) {
		/* sync lcd brightness */
		gpm_backlight_notify_system_idle_changed (backlight, FALSE);
		gpm_backlight_brightness_evaluate_and_set (backlight, FALSE);

		/* ensure backlight is on */
		ret = gpm_dpms_set_mode (backlight->priv->dpms, GPM_DPMS_MODE_ON, &error);
		if (!ret) {
			egg_warning ("failed to turn on DPMS: %s", error->message);
			g_error_free (error);
		}

	} else if (mode == GPM_IDLE_MODE_DIM) {

		/* sync lcd brightness */
		gpm_backlight_notify_system_idle_changed (backlight, TRUE);
		gpm_backlight_brightness_evaluate_and_set (backlight, FALSE);

		/* ensure backlight is on */
		ret = gpm_dpms_set_mode (backlight->priv->dpms, GPM_DPMS_MODE_ON, &error);
		if (!ret) {
			egg_warning ("failed to turn on DPMS: %s", error->message);
			g_error_free (error);
		}

	} else if (mode == GPM_IDLE_MODE_BLANK) {

		/* sync lcd brightness */
		gpm_backlight_notify_system_idle_changed (backlight, TRUE);
		gpm_backlight_brightness_evaluate_and_set (backlight, FALSE);

		/* get the DPMS state we're supposed to use on the power state */
		g_object_get (backlight->priv->client,
			      "on-battery", &on_battery,
			      NULL);
		if (!on_battery)
			dpms_method = gconf_client_get_string (backlight->priv->conf, GPM_CONF_BACKLIGHT_DPMS_METHOD_AC, NULL);
		else
			dpms_method = gconf_client_get_string (backlight->priv->conf, GPM_CONF_BACKLIGHT_DPMS_METHOD_BATT, NULL);

		/* convert the string types to standard types */
		dpms_mode = gpm_dpms_mode_from_string (dpms_method);

		/* check if method is valid */
		if (dpms_mode == GPM_DPMS_MODE_UNKNOWN || dpms_mode == GPM_DPMS_MODE_ON) {
			egg_warning ("BACKLIGHT method %s unknown. Using OFF.", dpms_method);
			dpms_mode = GPM_DPMS_MODE_OFF;
		}

		/* turn backlight off */
		ret = gpm_dpms_set_mode (backlight->priv->dpms, dpms_mode, &error);
		if (!ret) {
			egg_warning ("failed to change DPMS: %s", error->message);
			g_error_free (error);
		}

		g_free (dpms_method);
	}
}
/**
 * gpm_backlight_client_changed_cb:
 * @client: The up_client class instance
 * @backlight: This class instance
 *
 * Does the actions when the ac power source is inserted/removed.
 **/
static void
gpm_backlight_client_changed_cb (UpClient *client, GpmBacklight *backlight)
{
	gpm_backlight_brightness_evaluate_and_set (backlight, FALSE);
}
/**
 * gpm_backlight_init:
 * @brightness: This brightness class instance
 *
 * initialises the brightness class. NOTE: We expect laptop_panel objects
 * to *NOT* be removed or added during the session.
 * We only control the first laptop_panel object if there are more than one.
 **/
static void
gpm_backlight_init (GpmBacklight *backlight)
{
    backlight->priv = GPM_BACKLIGHT_GET_PRIVATE (backlight);

    /* record our idle time */
    backlight->priv->idle_timer = g_timer_new ();

    /* watch for manual brightness changes (for the popup widget) */
    backlight->priv->brightness = gpm_brightness_new ();
    g_signal_connect (backlight->priv->brightness, "brightness-changed",
                      G_CALLBACK (brightness_changed_cb), backlight);

    /* we use up_client for the ac-adapter-changed signal */
    backlight->priv->client = up_client_new ();
    g_signal_connect (backlight->priv->client, "changed",
                      G_CALLBACK (gpm_backlight_client_changed_cb), backlight);

    /* gets caps */
    backlight->priv->can_dim = gpm_brightness_has_hw (backlight->priv->brightness);

    /* watch for dim value changes */
    backlight->priv->settings = g_settings_new (GPM_SETTINGS_SCHEMA);
    g_signal_connect (backlight->priv->settings, "changed", G_CALLBACK (gpm_settings_key_changed_cb), backlight);

    /* set the main brightness, this is designed to be updated if the user changes the
     * brightness so we can undim to the 'correct' value */
    backlight->priv->master_percentage = g_settings_get_double (backlight->priv->settings, GPM_SETTINGS_BRIGHTNESS_AC);

    /* watch for brightness up and down buttons and also check lid state */
    backlight->priv->button = gpm_button_new ();
    g_signal_connect (backlight->priv->button, "button-pressed",
                      G_CALLBACK (gpm_backlight_button_pressed_cb), backlight);

    /* watch for idle mode changes */
    backlight->priv->idle = gpm_idle_new ();
    g_signal_connect (backlight->priv->idle, "idle-changed",
                      G_CALLBACK (idle_changed_cb), backlight);

    /* assumption */
    backlight->priv->system_is_idle = FALSE;
    backlight->priv->idle_dim_timeout = g_settings_get_int (backlight->priv->settings, GPM_SETTINGS_IDLE_DIM_TIME);
    gpm_idle_set_timeout_dim (backlight->priv->idle, backlight->priv->idle_dim_timeout);

    /* use a visual widget */
    backlight->priv->popup = gsd_media_keys_window_new ();
    gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (backlight->priv->popup),
            "gpm-brightness-lcd",
            TRUE);
    gtk_window_set_position (GTK_WINDOW (backlight->priv->popup), GTK_WIN_POS_NONE);

    /* DPMS mode poll class */
    backlight->priv->dpms = gpm_dpms_new ();

    /* we refresh DPMS on resume */
    backlight->priv->control = gpm_control_new ();
    g_signal_connect (backlight->priv->control, "resume",
                      G_CALLBACK (control_resume_cb), backlight);

    /* Don't do dimming on inactive console */
    backlight->priv->consolekit = egg_console_kit_new ();

    /* sync at startup */
    gpm_backlight_brightness_evaluate_and_set (backlight, FALSE, TRUE);
}