/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CExcelProperty.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 __CEXCELPROPERTY_H__
#define __CEXCELPROPERTY_H__

#include <stdio.h>
#include <string.h>

#include <sptk3/excel/CExcelBAT.h>

#include <vector>

namespace sptk {

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

#define PROPERTY_SIZE               0x80 ///< Property size, bytes

#define _NAME_SIZE_OFFSET           0x40 ///< Name size offset, bytes
#define _NO_INDEX                   -1   ///< No index mark

// useful offsets
#define _PROPERTY_TYPE_OFFSET       0x42 ///< Property type offset, bytes
#define _NODE_COLOR_OFFSET          0x43 ///< Node color offset, bytes
#define _PREVIOUS_PROPERTY_OFFSET   0x44 ///< Previous property offset, bytes
#define _NEXT_PROPERTY_OFFSET       0x48 ///< Next property offset, bytes
#define _CHILD_PROPERTY_OFFSET      0x4C ///< Child property offset, bytes
#define _STORAGE_CLSID_OFFSET       0x50 ///< Storage CLSID offset, bytes
#define _USER_FLAGS_OFFSET          0x60 ///< User flags offset, bytes
#define _SECONDS_1_OFFSET           0x64 ///< Seconds 1 offset, bytes
#define _DAYS_1_OFFSET              0x68 ///< Days 1 offset, bytes
#define _SECONDS_2_OFFSET           0x6C ///< Seconds 2 offset, bytes
#define _DAYS_2_OFFSET              0x70 ///< Days 2 offset, bytes
#define _START_BLOCK_OFFSET         0x74 ///< Start block offset, bytes
#define _SIZE_OFFSET                0x78 ///< Size offset offset, bytes

// node colors
#define _NODE_BLACK                 1    ///< Node color is BLACK
#define _NODE_RED                   0    ///< Node color is RED

   /// @brief Represents an internal file system property in Excel File
	class CExcelProperty {
		char    m_data[PROPERTY_SIZE];         ///< Property data buffer
		CBuffer m_streamData;                  ///< Property stream buffer
	public:
      /// @brief Constructor
      /// @param pname CString, property name
      /// @param ptype unsigned, property type: 1 (directory), 2 (file), or 5 (root entry)
      /// @param nodeColor unsigned, node color: 0 (red) or 1 (black)
      /// @param previousProperty unsigned, previous property index
      /// @param nextProperty unsigned, next property index
      /// @param firstChildPropety unsigned, first child property index
      /// @param startBlock unsigned, first block of the file described by this property
      /// @param fileLength unsigned, the actual length of the file described by this property
		CExcelProperty(
			std::string pname,
			unsigned ptype=0x5,
			unsigned nodeColor=0x0,
			unsigned previousProperty=0xFFFFFFFF,
			unsigned nextProperty=0xFFFFFFFF,
			unsigned firstChildPropety=0xFFFFFFFF,
			unsigned startBlock=0xFFFFFFFE,
			unsigned fileLength=0
		);

      /// @brief Constructor
      ///
      /// Creates property from internal Excel file' binary presentation
      /// @param data const char *, the bynary presentation of the property in internal Excel format
		CExcelProperty(const char *data);

      /// @brief Returns the property name
		std::string name() const;

      /// @brief Returns property type (1-directory, 2-file, 5-root entry)
		unsigned propertyType() const;

      /// @brief Returns binary presentation of the property
		const char *data() const { return m_data; }

      /// @brief Returns property stream buffer
		CBuffer& streamData() { return m_streamData; }

      /// @brief Finds the stream data connected to the property and loads them into m_streamData
      /// @param batTable CExcelBAT *, the existing BAT table
      /// @param f FILE *, input file
		void extract(CExcelBAT *batTable,FILE *f);

      /// @brief Returns the first block number for this property' stream in the BAT
		unsigned firstBATBlock() const;

      /// @brief Sets the first block number for this property' stream in the BAT
      /// @param sbo unsigned, the first block number
		void firstBATBlock(unsigned sbo);

      /// @brief Returns actual property' stream length
		unsigned fileLength() const;

      /// @brief Sets actual property' stream length
		void fileLength(unsigned fl);

      /// @brief Returns block count required to store the property' stream
		unsigned blockCount() const;
	};

   /// @brief The collection of properties
	class CExcelProperties : public std::vector<CExcelProperty *> {
	public:
      /// @brief Default constructor
		CExcelProperties() {}

      /// @brief Destructor
		~CExcelProperties() { clear(); }

      /// @brief Cleaner
		void clear();

      /// @brief Saves properties to file
		void save(FILE *f);

      /// @brief Returns number of blocks required to store the properties
		unsigned blocks() const;

      /// @brief Extracts properties from the file and header
      /// @param fileHeader CExcelHeader *, the Excel file header
      /// @param batTable CExcelBAT *, the Excel BAT table
      /// @param f FILE *, the input file
		void extract(CExcelHeader *fileHeader,CExcelBAT *batTable,FILE *f);

      /// @brief Finds a property by name
      /// @param name const char *, property name
		CExcelProperty *find(const char *name);
	};
   /// @}
}
#endif
