/*
 * * Copyright (C) 2010-2011 Ali <aliov@xfce.org>
 *
 * Licensed under the GNU General Public License Version 2
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <libxfce4util/libxfce4util.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <upower.h>

#include "xfpm-power-common.h"
#include "xfpm-enum-glib.h"

#include "xfpm-icons.h"


/**
 * xfpm_power_translate_device_type:
 *
 **/
const gchar *
xfpm_power_translate_device_type (guint type)
{
    switch (type)
    {
        case UP_DEVICE_KIND_BATTERY:
            return _("Battery");
        case UP_DEVICE_KIND_UPS:
            return _("UPS");
        case UP_DEVICE_KIND_LINE_POWER:
            return _("Line power");
        case UP_DEVICE_KIND_MOUSE:
            return _("Mouse");
        case UP_DEVICE_KIND_KEYBOARD:
            return _("Keyboard");
        case UP_DEVICE_KIND_MONITOR:
            return _("Monitor");
        case UP_DEVICE_KIND_PDA:
            return _("PDA");
        case UP_DEVICE_KIND_PHONE:
            return _("Phone");
        case UP_DEVICE_KIND_TABLET:
            return _("Tablet");
        case UP_DEVICE_KIND_COMPUTER:
            return _("Computer");
        case UP_DEVICE_KIND_UNKNOWN:
            return _("Unknown");
    }

    return _("Battery");
}

/**
 * xfpm_power_translate_technology:
 *
 **/
const gchar *
xfpm_power_translate_technology (guint value)
{
    switch (value)
    {
        case 0:
            return _("Unknown");
        case 1:
            return _("Lithium ion");
        case 2:
            return _("Lithium polymer");
        case 3:
            return _("Lithium iron phosphate");
        case 4:
            return _("Lead acid");
        case 5:
            return _("Nickel cadmium");
        case 6:
            return _("Nickel metal hybride");
    }

    return _("Unknown");
}

const gchar * G_GNUC_CONST
xfpm_battery_get_icon_index (UpDeviceKind type, guint percent)
{
    if (percent < 10)
    {
        return "000";
    }
    else if (percent < 30)
    {
        return "020";
    }
    else if (percent < 50)
    {
        return "040";
    }
    else if (percent < 70)
    {
        return "060";
    }
    else if (percent < 90)
    {
        return "080";
    }

    return "100";
}

/*
 * Taken from gpm
 */
gchar *
xfpm_battery_get_time_string (guint seconds)
{
    char* timestring = NULL;
    gint  hours;
    gint  minutes;

    /* Add 0.5 to do rounding */
    minutes = (int) ( ( seconds / 60.0 ) + 0.5 );

    if (minutes == 0)
    {
	timestring = g_strdup (_("Unknown time"));
	return timestring;
    }

    if (minutes < 60)
    {
	timestring = g_strdup_printf (ngettext ("%i minute",
			              "%i minutes",
				      minutes), minutes);
	return timestring;
    }

    hours = minutes / 60;
    minutes = minutes % 60;

    if (minutes == 0)
	timestring = g_strdup_printf (ngettext (
			    "%i hour",
			    "%i hours",
			    hours), hours);
    else
	/* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
	 * Swap order with "%2$s %2$i %1$s %1$i if needed */
	timestring = g_strdup_printf (_("%i %s %i %s"),
			    hours, ngettext ("hour", "hours", hours),
			    minutes, ngettext ("minute", "minutes", minutes));
    return timestring;
}

gchar *
xfpm_battery_get_icon_prefix_device_enum_type (UpDeviceKind type)
{
    /* mapped from
     * http://cgit.freedesktop.org/upower/tree/libupower-glib/up-types.h
     */
    if ( type == UP_DEVICE_KIND_BATTERY )
    {
        return g_strdup (XFPM_PRIMARY_ICON_PREFIX);
    }
    else if ( type == UP_DEVICE_KIND_UPS )
    {
        return g_strdup (XFPM_UPS_ICON_PREFIX);
    }
    else if ( type == UP_DEVICE_KIND_MOUSE )
    {
        return g_strdup (XFPM_MOUSE_ICON_PREFIX);
    }
    else if ( type == UP_DEVICE_KIND_KEYBOARD )
    {
        return g_strdup (XFPM_KBD_ICON_PREFIX);
    }
    else if ( type == UP_DEVICE_KIND_PHONE )
    {
        return g_strdup (XFPM_PHONE_ICON_PREFIX);
    }
    else if ( type == UP_DEVICE_KIND_PDA )
    {
        return g_strdup (XFPM_PDA_ICON_PREFIX);
    }
    else if ( type == UP_DEVICE_KIND_MEDIA_PLAYER )
    {
        return g_strdup (XFPM_MEDIA_PLAYER_PREFIX);
    }
    else if ( type == UP_DEVICE_KIND_LINE_POWER )
    {
        return g_strdup (XFPM_AC_ADAPTER_ICON);
    }
    else if ( type == UP_DEVICE_KIND_MONITOR )
    {
        return g_strdup (XFPM_MONITOR_PREFIX);
    }
    else if ( type == UP_DEVICE_KIND_TABLET )
    {
        return g_strdup (XFPM_TABLET_ICON_PREFIX);
    }
    else if ( type == UP_DEVICE_KIND_COMPUTER )
    {
        return g_strdup (XFPM_COMPUTER_ICON_PREFIX);
    }

    return g_strdup (XFPM_PRIMARY_ICON_PREFIX);
}

static gboolean
is_display_device (UpClient *upower, UpDevice *device)
{
    UpDevice *display_device = NULL;
    gboolean ret = FALSE;

#if UP_CHECK_VERSION(0, 99, 0)
    display_device = up_client_get_display_device (upower);
#else
    return FALSE;
#endif

    ret = g_strcmp0(up_device_get_object_path(device), up_device_get_object_path(display_device)) == 0 ? TRUE : FALSE;

    g_object_unref (display_device);

    return ret;
}

gchar*
get_device_icon_name (UpClient *upower, UpDevice *device)
{
    gchar *icon_name = NULL, *icon_prefix;
    guint type = 0, state = 0;
    gboolean online;
    gboolean present;
    gdouble percentage;

    /* hack, this depends on XFPM_DEVICE_TYPE_* being in sync with UP_DEVICE_KIND_* */
    g_object_get (device,
		  "kind", &type,
		  "state", &state,
		  "is-present", &present,
		  "percentage", &percentage,
		  "online", &online,
		   NULL);

    icon_prefix = xfpm_battery_get_icon_prefix_device_enum_type (type);

    if ( type == UP_DEVICE_KIND_LINE_POWER )
    {
	if ( online )
	{
	    icon_name = g_strdup_printf ("%s", XFPM_AC_ADAPTER_ICON);
	}
	else
	{
	    icon_name = g_strdup_printf ("%s060", XFPM_PRIMARY_ICON_PREFIX);
	}
    }
    else if ( type == UP_DEVICE_KIND_BATTERY || type == UP_DEVICE_KIND_UPS )
    {
	if (!present)
	{
	    icon_name = g_strdup_printf ("%s%s", icon_prefix, "missing");
	}
	else if (state == UP_DEVICE_STATE_FULLY_CHARGED )
	{
	    icon_name = g_strdup_printf ("%s%s", icon_prefix, "charged");
	}
	else if ( state == UP_DEVICE_STATE_CHARGING || state == UP_DEVICE_STATE_PENDING_CHARGE)
	{
	    icon_name = g_strdup_printf ("%s%s-%s", icon_prefix, xfpm_battery_get_icon_index (type, percentage), "charging");
	}
	else if ( state == UP_DEVICE_STATE_DISCHARGING || state == UP_DEVICE_STATE_PENDING_DISCHARGE)
	{
	    icon_name = g_strdup_printf ("%s%s", icon_prefix, xfpm_battery_get_icon_index (type, percentage));
	}
	else if ( state == UP_DEVICE_STATE_EMPTY)
	{
	    icon_name = g_strdup_printf ("%s%s", icon_prefix, "000");
	}
    }
    else
    {

	if ( state == UP_DEVICE_STATE_EMPTY || state == UP_DEVICE_STATE_FULLY_CHARGED ||
             state == UP_DEVICE_STATE_DISCHARGING || state == UP_DEVICE_STATE_CHARGING )
            icon_name = icon_prefix;
	else if (is_display_device (upower, device))
	{
	    /* Desktop system with no batteries */
	    icon_name = g_strdup_printf ("%s", XFPM_AC_ADAPTER_ICON);
	}
	else
	{
	    icon_name = g_strdup_printf ("%smissing", icon_prefix);
	}
    }

    return icon_name;
}

gchar*
get_device_description (UpClient *upower, UpDevice *device)
{
    gchar *tip = NULL;
    gchar *est_time_str = NULL;
    guint type = 0, state = 0;
    gchar *model = NULL, *vendor = NULL;
    gboolean present, online;
    gdouble percentage;
    guint64 time_to_empty, time_to_full;

    /* hack, this depends on XFPM_DEVICE_TYPE_* being in sync with UP_DEVICE_KIND_* */
    g_object_get (device,
                  "kind", &type,
                  "vendor", &vendor,
                  "model", &model,
                  "state", &state,
                  "is-present", &present,
                  "percentage", &percentage,
                  "time-to-empty", &time_to_empty,
                  "time-to-full", &time_to_full,
                  "online", &online,
                   NULL);

    if (is_display_device (upower, device))
    {
        g_free (vendor);
        vendor = g_strdup (_("Computer"));

        g_free (model);
        model = g_strdup ("");
    }

    /* If we get a vendor or model we can use it, otherwise translate the
     * device type into something readable (works for things like ac_power)
     */
    if (g_strcmp0(vendor, "") == 0 && g_strcmp0(model, "") == 0)
        vendor = g_strdup_printf ("%s", xfpm_power_translate_device_type (type));

    if ( state == UP_DEVICE_STATE_FULLY_CHARGED )
    {
        if ( time_to_empty > 0 )
        {
            est_time_str = xfpm_battery_get_time_string (time_to_empty);
            tip = g_strdup_printf (_("<b>%s %s</b>\nFully charged (%0.0f%%, %s runtime)"),
                                   vendor, model,
                                   percentage,
                                   est_time_str);
            g_free (est_time_str);
        }
        else
        {
            tip = g_strdup_printf (_("<b>%s %s</b>\nFully charged (%0.0f%%)"),
                                   vendor, model,
                                   percentage);
        }
    }
    else if ( state == UP_DEVICE_STATE_CHARGING )
    {
        if ( time_to_full != 0 )
        {
            est_time_str = xfpm_battery_get_time_string (time_to_full);
            tip = g_strdup_printf (_("<b>%s %s</b>\nCharging (%0.0f%%, %s)"),
                                   vendor, model,
                                   percentage,
                                   est_time_str);
            g_free (est_time_str);
        }
        else
        {
            tip = g_strdup_printf (_("<b>%s %s</b>\nCharging (%0.0f%%)"),
                                   vendor, model,
                                   percentage);
        }
    }
    else if ( state == UP_DEVICE_STATE_DISCHARGING )
    {
        if ( time_to_empty != 0 )
        {
            est_time_str = xfpm_battery_get_time_string (time_to_empty);
            tip = g_strdup_printf (_("<b>%s %s</b>\nDischarging (%0.0f%%, %s)"),
                                   vendor, model,
                                   percentage,
                                   est_time_str);
            g_free (est_time_str);
        }
        else
        {
            tip = g_strdup_printf (_("<b>%s %s</b>\nDischarging (%0.0f%%)"),
                                   vendor, model,
                                   percentage);
        }
    }
    else if ( state == UP_DEVICE_STATE_PENDING_CHARGE )
    {
        tip = g_strdup_printf (_("<b>%s %s</b>\nWaiting to discharge (%0.0f%%)"),
                               vendor, model,
                               percentage);
    }
    else if ( state == UP_DEVICE_STATE_PENDING_DISCHARGE )
    {
        tip = g_strdup_printf (_("<b>%s %s</b>\nWaiting to charge (%0.0f%%)"),
                               vendor, model,
                               percentage);
    }
    else if ( state == UP_DEVICE_STATE_EMPTY )
    {
        tip = g_strdup_printf (_("<b>%s %s</b>\nis empty"),
                               vendor, model);
    }
    else
    {
        if (type == UP_DEVICE_KIND_LINE_POWER)
        {
            /* On the 2nd line we want to know if the power cord is plugged
             * in or not */
            tip = g_strdup_printf (_("<b>%s %s</b>\n%s"),
                           vendor, model, online ? _("Plugged in") : _("Not plugged in"));
        }
	else if (is_display_device (upower, device))
	{
	    /* Desktop pc with no battery, just display the vendor and model,
	     * which will probably just be Computer */
	    tip = g_strdup_printf (_("<b>%s %s</b>"), vendor, model);
	}
        else
        {
            /* unknown device state, just display the percentage */
            tip = g_strdup_printf (_("<b>%s %s</b>\nUnknown state"),
                           vendor, model);
        }
    }

    g_free(model);
    g_free(vendor);

    return tip;
}
