/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CExcelBook.h  -  description
                             -------------------
    begin                : Mon Jan 19 2004
    copyright            : (C) 2000-2006 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 __CEXCELBOOK_H__
#define __CEXCELBOOK_H__

#include <sptk3/excel/CExcelPalette.h>
#include <sptk3/excel/CExcelCellFormat.h>
#include <sptk3/excel/CExcelSheet.h>
#include <sptk3/excel/CExcelStyle.h>
#include <sptk3/excel/CExcelHeader.h>
#include <sptk3/excel/CExcelBAT.h>
#include <sptk3/excel/CExcelProperty.h>
#include <sptk3/excel/CExcelSST.h>
#include <sptk3/CStrings.h>
#include <stdio.h>

namespace sptk {

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

   /// Excel book reading/writing progression callback
	typedef void (*CExcelBookCallback)(const char *operationName,int percentage);

   /// @brief The Excel book
	class SP_EXPORT CExcelBook {
		friend class CExcelSheet;
	protected:
		std::string           m_name;              ///< Abstract workbook name
		std::string           m_lastError;         ///< Last processing error
		int                   m_codePage;          ///< Encoding type
		short                 m_BIFFversion;       ///< Excel BIFF format version
		CExcelRecordList      m_records;           ///< The list of records from Excel file
		int                  *m_sstRecordOffsets;  ///< Excel record offsets
		int                   m_sstRecordCount;    ///< Excel record count
		unsigned              m_bofPosition;       ///< The position of the first BOF in the file
		CExcelBookCallback    m_callback;          ///< Load/save progression callback
		CExcelStyles          m_styles;            ///< The list of global styles

      /// @brief Computes the number of blocks (rounded up) using file positions
      /// @param start unsigned, the start position in the file
      /// @param end unsigned, the end position in the file
      /// @param blockSize unsigned, the size of the block in the file
		unsigned blockCount(unsigned start,unsigned end,unsigned blockSize=BIG_BLOCK_SIZE);

      /// @brief Processes one Excel record
		void process_item(const CExcelRecord& record);

      /// @brief Parses Excel File
		int  scanExcelFile(FILE *f);

      /// @brief Parses Excel File for sheet information
		int  scanSheetsInfo(FILE *f);

      /// Parses Workbook Globals
		int  parseWorkBookGlobals(unsigned& dataStart);

      /// @brief Decodes Excel shared string record
		int  decodeSSTrecord(const CExcelRecord& record);

      /// @brief Decodes Excel extended shared string record
		int decodeEXTSSTrecord(const CExcelRecord& record);

      /// @brief Saves Excel records for writing into the CExcelRecords
      /// @param records CExcelRecords&, the output set of records
		void saveRecords(CExcelRecordsBuffer& records);
	protected:
		CExcelHeader          m_excelHeader;      ///< Excel file header
		CExcelBAT             m_excelBAT;         ///< Excel file Block Allocation Table (BAT)
		CExcelBAT             m_excelSBAT;        ///< Excel file Small Block Allocation Table (SBAT)
		CExcelProperties      m_excelProperties;  ///< Excel file Properties
		CBuffer              *m_workBookData;     ///< Workbook records buffer

      /// @brief Calls a callback function (if set)
		void do_callback(const char *operation,int percentage);

	public:
		CExcelSheets          sheets;             ///< The list of spreadsheets
		CExcelSST             sharedStringTable;  ///< The list of shared strings
		CExcelCellFormats     xfRecords;          ///< The list of formats
		CExcelPalette         palette;            ///< The list of the available colours

      /// @brief Constructor
      /// @param name CString, an abstract name to associate with the workbook
		CExcelBook(std::string name="");

      /// @brief Destructor
		~CExcelBook();

      /// @brief Clears inside structure completely
		void clear();

      /// @brief Clears inside structure completely
      /// 
      /// Also creates the minimal set of fonts, formats, etc.
		void init();

      /// @brief Returns an abstract workbook name
		const std::string& name() const { return m_name; }

      /// @brief Sets an abstract workbook name
		void name(const char *nm) { m_name = nm; }

      /// @brief Reads the Excel file
      /// @param fileName CString, the name of the input file
		int readExcelFile(std::string fileName);

      /// @brief Reads the CSV file
      /// The sheet is created automatically for every imported CSV file
      /// @param fileName CString, the name of the input file
		int readCSVFile(std::string fileName);

      /// @brief Saves the Excel file
      /// @param fileName CString, the name of the output file
		int writeExcelFile(std::string fileName);

      /// @brief Saves the Excel file
      /// @param file FILE *, the external output file
		int writeExcelFile(FILE *file);

      /// @brief Saves the CSV file
      /// @param fileName CString, the name of the output file
      /// @param sheetNumber unsigned, the number of sheet to export (the default is 0, the very first sheet)
		int writeCSVFile(std::string fileName,unsigned sheetNumber=0);

      /// @brief Saves the CSV file
      /// @param file FILE *, the external output file
      /// @param sheetNumber unsigned, the number of sheet to export (the default is 0, the very first sheet)
		int writeCSVFile(FILE *file,unsigned sheetNumber=0);

      /// @brief Reports the last error
		const char * lastError() { return m_lastError.c_str(); }

      /// @brief Returns load/save progression callback
		CExcelBookCallback callback() const { return m_callback; }

      /// @brief Defines load/save progression callback
      /// @param cb CExcelBookCallback, the new callback function
		void callback(CExcelBookCallback cb) { m_callback = cb; }

      /// @brief Returns a numeric format for the index
      /// @param index unsigned, logical index for the numeric format
		const CExcelNumericFormat& numericFormat(unsigned index) const { return xfRecords.numericFormat(index); }

      /// @brief Creates a new sheet in the book
		CExcelSheet *newSheet(const char *sheetName);

      /// @brief Adds a new font to the font list, or finds similar existing font
      /// @param fontName const char *, font name
      /// @param fontHeight unsigned, font height in points
      /// @param fontAttr unsigned, font attr (EFM_ATTR_ITALIC,EFM_ATTR_BOLD,EFM_ATTR_UNDERLINE,EFM_ATTR_STRIKEOUT)
      /// @param charSet unsigned, character set as defined in Windows API LOGFONT structure
      /// @returns logical index of the new or existing font
		unsigned defineFont(const char *fontName,unsigned fontHeight,unsigned fontAttr=0,unsigned charSet=0);

      /// @brief Returns the font by the logical font index.
      /// Font with index 4 is a dummy font and shouldn't be used.
		const CExcelFont& font(unsigned fontIndex) const;

      /// @brief Defines a new cell format from the scratch
      /// @param fontIndex unsigned, the logical index of the existing font
      /// @param numericFormatIndex unsigned, the logical index of the existing numeric format
      /// @param align unsigned, the combination of align flags from enum CExcelCellAlignFlags
      /// @param wrap bool, the cell text wrap flag
      /// @param border CExcelBorderLine, the type of the cell border line
      /// @param pattern unsigned, one of the Excel standard pattern types 0..0x12
      /// @param patternForeColorIndex unsigned, the pattern fore color index in the palette
      /// @param patternBackColorIndex unsigned, the pattern back color index in the palette
      /// @returns the pointer on the new cell format
		CExcelCellFormat *defineFormat(
			unsigned fontIndex=0,
			unsigned numericFormatIndex=0,
			unsigned align=0,
			bool     wrap=false,
			CExcelBorderLine border=CBL_NONE,
			unsigned pattern=0,
			unsigned patternForeColorIndex=EPC_BLACK,
			unsigned patternBackColorIndex=EPC_WHITE
		);
	};
   /// @}
}
#endif
