/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CExcelSheet.h  -  description
                             -------------------
    begin                : Mon Jan 19 2004
    copyright            : (C) 2004 by Alexey S.Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   This library 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 Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#ifndef __CEXCELSHEET_H__
#define __CEXCELSHEET_H__

#include <stdio.h>

#include <sptk3/excel/CExcelRows.h>
#include <sptk3/excel/CExcelRecordsBuffer.h>
#include <sptk3/excel/CExcelCellFormat.h>
#include <sptk3/excel/CExcelColumn.h>

#include <vector>

namespace sptk {

   /// @addtogroup excel Excel Classes
   /// @{

	class CExcelBook;

   /// Class CExcelSheet represents an Excel spreadsheet
	class SP_EXPORT CExcelSheet {
		friend class CExcelBook;
	private:
		std::string    m_sheetName;           	///< Spreadsheet name
		char           m_format_buffer[64];   	///< Spreadsheet formats
		const char    *m_lastError;           	///< Last processing error
		CExcelBook    *m_parentBook;          	///< Spreadsheet's parent book
		CExcelRow     *m_currentRow;          	///< Current row in the dataset.
		short          m_BIFFversion;         	///< Excel format version
		CExcelColumns  m_columns;             	///< Excel columns info
		unsigned			m_lastComputedPosition;	///< Last computed position

      /// Processes an Excel file record
		void        process_item (int rectype, int reclen, char *rec);

      /// Formats the floating point data with the format ixf
		char *      format_double(double d,int ixf);
	protected:
		int                  m_sheetPosition;       ///< Spreadsheet position
		CExcelRecordsBuffer  m_recordsBuffer;       ///< Internal buffer for ExcelRecords

      /// Encodes sheet's data into internal records buffer
      /// The resulting recordset is used later to save sheet into Excel file.
      /// @param sheetStreamPosition unsigned, the position of the sheet BOF in the stream
		void encode(unsigned sheetStreamPosition);

      /// Returns internal recordsBuffer
		const CExcelRecordsBuffer& recordsBuffer() const { return m_recordsBuffer; }

      /// Reads the sheet from CSV file
      /// @param fileName CString, the name of the input file
		int readCSVFile(std::string fileName);

      /// Saves the sheet into CSV file
      /// @param fileName CString, the name of the output file
		int writeCSVFile(std::string fileName);

      /// Saves the sheet into CSV file
      /// @param file FILE *, the external output file
		int writeCSVFile(FILE *file);

      /// Loads spreadsheet from the Excel file
		int parseWorkSheet(CBuffer& excelData,unsigned& pos);

	public:
      /// Spreadsheet rows
		CExcelRows rows;

	protected:
      /// Protected constructor, only CExcelBook can create new CExcelSheet
      /// @param name const char *, spreadsheet name
      /// @param filePosition int, spreadsheet position in Excel file
      /// @param parentBook CExcelBook *, parent Excel book
		CExcelSheet(const char *name,int filePosition,CExcelBook *parentBook);

	public:
      /// Returns spreadsheet name
		const std::string& name() const { return m_sheetName; }

      /// Sets spreadsheet name
		void name(const char *nm) { m_sheetName = nm; }

      /// Spreadsheet's parent book
		const CExcelBook& book() const { return *m_parentBook; } 

      /// Clears the spreadsheet data
		void clearData();

      /// Returns the width of the column
      /// @param col unsigned, column number
      /// @returns the width of the column - in characters of default font
		unsigned colWidth(unsigned col) const { return m_columns[col]->width(); }

      /// Sets the width of the column
      /// @param col unsigned, column number
      /// @param w unsigned, the width of the column - in characters of default font
		void colWidth(unsigned col,unsigned w) { m_columns[col]->width(w); }

      /// Returns the number of the rows in spreadsheet
		unsigned rowCount() const { return rows.size(); }

      /// Returns the number of the columns in spreadsheet
		unsigned colCount() const { return rows[0].size(); }

      /// Sets the data in the cell
      /// @param row unsigned, cell row number
      /// @param col unsigned, cell column number
      /// @param value CVariant, cell value
      /// @param format CExcelFormat *, pointer to the format record
		int setValue(unsigned row,unsigned col,CVariant value,const CExcelCellFormat *format);

      /// Sets the RK (integer,float,date,datetime) data in the cell
      /// @param row unsigned, cell row number
      /// @param col unsigned, cell column number
      /// @param value double, cell value
      /// @param rkType CVariantType, number type (integer,float)
      /// @param format CExcelFormat *, pointer to the format record
		int setRKValue(unsigned row,unsigned col,double value,CVariantType rkType,const CExcelCellFormat *format);

      /// Returns spreadsheet position in Excel file
		unsigned filePosition() const { return m_sheetPosition; }

      /// Changes the size of the spreadsheet
		void resize(unsigned height,unsigned width);

      /// Sets format to a group of cells
      /// @param format const CExcelCellFormat *, the cell format
      /// @param row1 unsigned, the first row in the cell group
      /// @param col1 unsigned, the first column in the cell group
      /// @param row2 unsigned, the last row in the cell group
      /// @param col2 unsigned, the last column in the cell group
		void format(const CExcelCellFormat *format,unsigned row1,unsigned col1,unsigned row2,unsigned col2);

      /// Updates vertical positions for the sheet rows
      /// Uses m_lastComputedPosition to start computations from
		void updatePositions();
	};

   /// The list of Excel spreadsheets
	class SP_EXPORT CExcelSheets : public std::vector<CExcelSheet *> {
		CExcelBook  *m_parentBook; ///< Parent Excel book
	public:

      /// Default constructor
		CExcelSheets() { m_parentBook = 0L; }

      /// Destructor
		~CExcelSheets() { clear(); }

      /// Cleaner
		void clear();

      /// Attach the list to the parent Excel book
		void attach(CExcelBook *book) { m_parentBook = book; }
	};
   /// @}
}
#endif
