/**
 * @file
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 *
 * The iWear Framework 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 as in version 2 of the License.

 * 
 * The iWear Framework 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
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __IWPOWER_POWER_BASE_H
#define __IWPOWER_POWER_BASE_H

#ifndef __IWEAR_MODULE_ENUMS_H
#include <iwear/module_enums.h>
#endif

#ifndef __IWEAR_UTILITY_H
#include <iwear/utility.h>
#endif

#ifndef __IWEAR_EXCEPTIONS_H
#include <iwear/exceptions.h>
#endif

#ifndef __IWSENS_SENSOR_H
#include <iwsens/sensor.h>
#endif

#ifndef __IWPOWER_POWER_ENUMS_H
#include <iwpower/power_enums.h>
#endif

#include <bitset>
using namespace std;

namespace iwear
{
    namespace sensor
    {
	namespace power
	{

class PowerManager;
/**
 * This is a base class for all possible acpi values we want to read. It does
 * nothing, and therefore has nothing implemented. It throws exceptions on get_
 * functions, and returns all false on has_ functions. But since they are
 * virtual, you may derive from it, and implement what you can do...
 * @note All the has_ functions are to check if the corresponding get_ function
 * is supported. If it returns false, the call to the get_ function will fail
 * and throw
 */

class power_base : public Sensor
{
private:
    friend class PowerManager;
    power_base(void);
protected:
    mutable double last_cur_update;

    mutable int32_t last_cur;
    mutable int32_t act_rate;
    mutable time_t act_remain;

    mutable bitset<num_eh_capabilities> have_set;

    PowerManager* PMan;
public:
    /**
     * Generic has check to check for saved capability status
     */
    virtual bool has( eh_capabilities h ) const { return have_set[h]; }

    /**
     * Get an integer returning capability. Throws if the requested does not
     * return int.
     */
    virtual int32_t get( eh_capabilities ch ) const;
    
    /**
     * Get an float returning capability. Throws if the requested does not
     * return float.
     */
    virtual float getf( eh_capabilities ch ) const;
    
    /**
     * Returns a psunion containing the value of the capability. The actual
     * union part is specific to the capability requested.
     */
    virtual psunion getu( eh_capabilities ch) const;

    power_base(PowerManager*);

   /**
    * All the values gathered here are available in two variants. First of all,
    * it might be possible that the values can be read on demand, so they
    * should be. If this is not the case, e.g. because the values are all read
    * in a bunch, the update should read all available values. Therefore,
    * before reading any, its best to call the update.
    */
    virtual void update( void ) const { }

    virtual sensor_type get_sensor_type( void ) const { return power_sensor; }

    /**
     * Needs to be implemented by deriving class
     */
    virtual powersensor_type get_powersensor_type( void ) const = 0;
    
    /**
     * Returns an energy state enum saying if the AC Adapter is on or offline
     */
    virtual energy_state get_ac_status( void ) const;
    virtual bool         has_ac_status( void ) const { return have_set[eh_ac_status]; }

    /**
     * Returns an enum denoting the battery loading state, e.g. discharging,
     * charging, charged etc.
     */
    virtual battery_state get_bat_status( void ) const;
    virtual bool          has_bat_status( void ) const { return have_set[eh_bat_status]; }

    /**
     * returns the design capacity of the battery in mAh
     */
    virtual int32_t get_bat_design( void ) const;
    virtual bool     has_bat_design( void ) const { return have_set[eh_bat_design]; }

    /**
     * Get the capacity of the last fully loaded state in mAh
     */
    virtual int32_t get_bat_last( void ) const;
    virtual bool     has_bat_last( void ) const { return have_set[eh_bat_last]; }

    /**
     * Gets the current load of the battery in mAh
     */
    virtual int32_t get_bat_current( void ) const;
    virtual bool     has_bat_current( void ) const { return have_set[eh_bat_current]; }

    /**
     * Get the current discharge rate of the battery in mA
     */
    virtual int32_t get_bat_rate( void ) const;
   /**
    * From the current capacity we can calculate the rate if not directly supported.
    */
    virtual bool     has_bat_rate( void ) const { return have_set[eh_bat_rate]; }

    /**
     * Gets the number of seconds the battery will last
     */
    virtual time_t get_bat_remain( void ) const;
    virtual bool   has_bat_remain( void ) const { return (( has_bat_rate() && has_bat_design() ) || has_bat_current()) && ( has_ac_status() && get_ac_status() != ac_online) ; }

    /**
     * Gets the percentage thats left in the battery
     * @note This may be more than 100% in the case the battery is currently
     * loading beyond last full charged state
     */
    virtual float get_bat_totalremain( void ) const;
    virtual bool   has_bat_totalremain( void ) const { return has_bat_current()&&(has_bat_design()||has_bat_last() ); } 

    /**
     * Gets the voltage the battery is designed for
     */
    virtual int32_t get_bat_designvoltage( void ) const;
    virtual bool     has_bat_designvoltage( void ) const { return have_set[eh_bat_designvoltage]; }

    /**
     * Gets the current voltage the computer is running at
     * @note Is usually higher than the batteries design voltage when running on AC
     */
    virtual int32_t get_bat_currentvoltage( void ) const;
    virtual bool     has_bat_currentvoltage( void ) const { return have_set[eh_bat_currentvoltage]; }

    /**
     * Returns a string telling the model descriptor of the battery, will never
     * change
     */
    virtual const string& get_bat_model( void ) const;
    virtual bool          has_bat_model( void ) const{ return have_set[eh_bat_model]; }

    // More like lcd, throttle etc. will follow 

    /**
     * Gets the status of the lid switch, e.g. open or closed
     */ 
    virtual lid_state get_lid_state( void ) const;
    virtual bool      has_lid_state( void ) const { return have_set[eh_lid_state]; }

    /**
     * Gets the cpu temperature as Degree Celsius
     */
    virtual float get_cpu_temp( void ) const;
    virtual bool  has_cpu_temp( void ) const { return have_set[eh_cpu_temp]; }

    /**
     * Gets the LCDs brightness as computer specific value
     */
    virtual int32_t get_lcd_brightness( void ) const;
    virtual bool     has_lcd_brightness( void ) const { return have_set[eh_lcd_brightness]; }
};

}
}
}

#endif
