/**************************************************************

selection.h (C-Munipack project)
Table of selected stars
Copyright (C) 2008 David Motl, dmotl@volny.cz

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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

**************************************************************/

#ifndef MUNIWIN_TABLE_CLASSE_H
#define MUNIWIN_TABLE_CLASSE_H

#include "helper_classes.h"
#include "file_classes.h"

//
// Channel descriptor
//
class CChannel
{
public:
	// Type of data stored in the channel
	enum tChannelInfo {
		DATA_UNDEFINED,				// Nothing
		DATA_JD,					// Julian date
		DATA_JD_HEL,				// Heliocentric Julian date
		DATA_VCMAG,					// V-C differential magnitude
		DATA_VMAG,					// Variable star instrumental magnitude
		DATA_CMAG,					// Comparison star instrumental magnitude
		DATA_KMAG,					// First check star instrumental magnitude
		DATA_MAG_OTHER,				// Magnitude (other)
		DATA_MAG_DEVIATION,			// Standard deviation of magnitudes
		DATA_HELCOR,				// Heliocentric correction
		DATA_AIRMASS,				// Airmass coefficient
		DATA_OFFSET,				// Pixel offset
		DATA_FREQUENCY,				// Number of items (frames, objects, ...)
		DATA_ALTITUDE,				// Altitude
		DATA_FRAME_ID,				// Frame #
		DATA_OBJECT_ID,				// Object #
		DATA_APERTURE_ID,			// Aperture #
		DATA_TEMPERATURE,			// Temperature in C
		DATA_DURATION,				// Duration in seconds
		DATA_ADU,					// Value in ADU
		DATA_SIZE,					// Width or height in pixels
		DATA_FILENAME				// File name
	};

	// How the data in this channel get exported to a file
	enum tExportFlags
	{
		EXPORT_SKIP			= (1<<0),	// Do not export this channel
		EXPORT_VALUE_ONLY	= (1<<1)	// Export only value, ignore error
	};

	// How the data are displayed in the table
	enum tDisplayFlags
	{
		DISPLAY_SKIP		= (1<<0),	// Do not show this channel
	};

	// Constructors
	CChannel(class CTable *tab, int y_col, int u_col, tChannelInfo info);

	// Destructor
	virtual ~CChannel(void);

	// Get table column for values
	int Column(void) const
	{ return m_Column; }

	// Get table column for errors
	int ColumnU(void) const
	{ return m_ColumnU; }

	// Is the channel valid?
	bool Valid(void) const
	{ return m_Column>=0; }

	// What kind of information this channel specify?
	tChannelInfo Info(void) const
	{ return m_Info; }

	// Name of the column with values
	const gchar *Name(void) const
	{ return m_Name; }

	// Get unit name (m, s, days, deg, ...)
	// Returns pointer to static buffer, you don't need to make copy
	const gchar *Unit(void) const;

	// Get default number of decimal places
	int Precision(void) const 
	{ return m_Precision; }

	// Minimum value
	double Min(void) const;

	// Maximum value
	double Max(void) const;

	// Maximum error value
	double MaxU(void) const;

	// Enable/disable exporting of this column
	void SetExportFlags(unsigned flags) 
	{ m_ExportFlags = flags; }
	unsigned ExportFlags(void) const
	{ return m_ExportFlags; }

	// Enable/disable exporting of this column
	void SetDisplayFlags(unsigned flags) 
	{ m_DisplayFlags = flags; }
	unsigned DisplayFlags(void) const
	{ return m_DisplayFlags; }

private:
	CTable			*m_Table;
	int				m_Column, m_ColumnU;
	char			*m_Name;
	bool			m_Exported;
	tChannelInfo	m_Info;
	CmpackType		m_DataType;
	int				m_Precision;
	unsigned		m_ExportFlags, m_DisplayFlags;

	// Assignment operator
	CChannel &operator=(const CChannel&);

	CChannel(const CChannel&);
};

//
// Table of channels
//
class CChannels
{
public:
	// Constructor(s)
	CChannels(void);
	
	// Destructor
	virtual ~CChannels();

	// Get number of apertures
	int Count(void) const
	{ return m_Count; }

	// Returns true if the table is empty
	bool Empty(void) const
	{ return m_Count==0; }

	// Clear the table
	void Clear(void);

	// Add a channel, if the channel with the column index is 
	// already in the table, it changes its parameters
	void Add(CChannel *item);

	// Find first channel by column index
	int FindColumn(int column) const;

	// Find first channel by name
	int FindFirst(const gchar *name) const;

	// Find first channel by given info
	int FindFirst(CChannel::tChannelInfo info) const;

	// Get aperture by index
	const CChannel *Get(int index) const;
	CChannel *Get(int index);

	// Get column by index
	int GetColumn(int index) const;

	// Get column by index
	int GetColumnU(int index) const;

	// Get name by index
	const gchar *GetName(int index) const;

	// Get color by index
	const GdkColor *GetColor(int index) const; 

	// Get channel info
	CChannel::tChannelInfo GetInfo(int index) const;

	// Get unit name (m, s, days, deg, ...)
	// Returns pointer to static buffer, you don't need to make copy
	const gchar *GetUnit(int index) const;

	// Minimum value
	double GetMin(int index) const;

	// Maximum value
	double GetMax(int index) const;

	// Maximum error value
	double GetMaxU(int index) const;

	// Get "exported" flag
	unsigned GetExportFlags(int index) const;
	void SetExportFlags(int index, unsigned flags);

	// Get "display" flag
	unsigned GetDisplayFlags(int index) const;
	void SetDisplayFlags(int index, unsigned flags);

	// Get default number of decimal places
	int GetPrecision(int index) const;

protected:
	int			m_Count, m_Capacity;
	CChannel	**m_List;

private:
	// Disable copy constructor and assigment operator
	CChannels &operator=(const CChannels&);
	CChannels(const CChannels&);
};

//
// Table class interface
//
class CTable
{
public:
	enum tExportFlags {
		EXPORT_NO_HEADER			= (1<<0),	// Suppress table header 
		EXPORT_NULVAL_ZERO			= (1<<1),	// Replace invalid value by zero 
		EXPORT_NULVAL_SKIP_ROW		= (1<<2)	// Skip rows that contain an invalid value 
	};

	// Default constructor
	CTable(void);

	// Constructor with initialization
	CTable(CmpackTableType type);

	// Constructor with initialization (makes its own reference)
	CTable(CmpackTable *handle);

	// Destructor
	virtual ~CTable(void);

	// Load table from a file
	bool Load(const gchar *filepath, GError **error = NULL);

	// Export a table to a file
	bool Save(const gchar *filepath, GError **error = NULL);

	// Free internal data
	void Clear(void);

	// Makes deep copy of the table
	bool MakeCopy(const CTable &table, GError **error = NULL);

	// Is table valid?
	bool Valid(void) const
	{ return m_Handle!=NULL; }

	// Get type identifier of the table
	CmpackTableType Type(void) const;

	// Get header field by index
	bool GetParam(int index, char **key, char **val) const;

	// Set header field
	void SetParam(const char *key, const char *value);

	// Get number of rows
	int Rows(void) const;

	// Browsing
	bool Rewind(void);
	bool Next(void);
	bool EndOfTable(void);

	// Primary key column
	int PKColumn(void);

	// Get list of dependent channels
	CChannels *ChannelsX(void);

	// Get list of independent channels
	CChannels *ChannelsY(void);

	// Get color filter name
	const char *Filter(void) const;

	// Get aperture index
	int Aperture(void) const;

	// Make graph data
	CmpackGraphData *ToGraphData(int x_channel, int y_channel);

	// Make table model
	GtkTreeModel *ToTreeModel(void);

	// Set view parameters
	void SetView(CmpackGraphView *view, int x_channel, int y_channel, bool no_errors,
		const gchar *user_name_x = NULL, const gchar *user_name_y = NULL,
		tDateFormat datef = JULIAN_DATE, bool fixed_x = false, double xmin = 0, double xmax = 0,
		bool fixed_y = false, double ymin = 0, double ymax = 0);

	// Set view parameters
	void SetView(GtkTreeView *view);

	// Export a table to a file
	bool ExportTable(const gchar *filepath, const gchar *format, unsigned flags, GError **error);

	// Export file header
	bool ExportHeader(const gchar *filepath, const gchar *format, unsigned flags, GError **error) const;

	// Get double value from actual row
	bool GetDbl(int column, double *val) const;

	// Get string value from actual row
	bool GetStr(int column, gchar **val) const;

	// Get min-max for given channel
	bool GetMinMaxX(int x_channel, double &min, double &max);
	bool GetMinMaxY(int y_channel, bool no_errors, double &min, double &max);

	// Find row by primary key
	bool Find(int pk_value) const;

	// Delete current row
	void Delete(void);

	// Invalidate cached data
	void InvalidateCache(void);

private:
	friend class CChannel;

	enum tCacheFlags {
		CF_CHANNELS = (1<<0)
	};
	
	CmpackTable		*m_Handle;
	unsigned		m_CacheFlags;
	CChannels		m_ChannelsX, m_ChannelsY;
	int				m_PKColumn;

	// Update list of channels
	void UpdateChannels(void);

	// Export table in CSV format
	void ExportTable(CCSVWriter &writer, unsigned flags);

	// Export header in CSV format
	void ExportHeader(CCSVWriter &writer, unsigned flags) const;

private:
	// Disable copy constructor and assigment operator
	CTable(const CTable &tab);
	CTable &operator=(const CTable &orig);
};

#endif
