/* WordPerfectCollector: Collects sections and runs of text from a
 * wordperfect file (and styles to go along with them) and writes them
 * to a target file
 *
 * Copyright (C) 2002-2004 William Lachance (william.lachance@sympatico.ca)
 * Copyright (C) 2003-2004 Net Integration Technologies (http://www.net-itech.com)
 * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 * For further information visit http://libwpd.sourceforge.net
 *
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#ifndef _WORDPERFECTCOLLECTOR_H
#define _WORDPERFECTCOLLECTOR_H

#include "SectionStyle.hxx"

#include <config.h>
#include <libwpd/libwpd.h>
#include "shared_headers.h"
#include <vector>
#include <map>
#include <stack>

class DocumentElement;
class DocumentHandler;
class TagOpenElement;
class FontStyle;
class ListStyle;

class ParagraphStyle;
class SpanStyle;
class TableStyle;
class PageSpan;

// the state we use for writing the final document
typedef struct _WriterDocumentState WriterDocumentState;
struct _WriterDocumentState
{
	_WriterDocumentState();
		
	bool mbFirstElement;
	bool mbInFakeSection;
	bool mbListElementOpenedAtCurrentLevel;
	bool mbTableCellOpened;
	bool mbHeaderRow;
	bool mbInNote;
};

enum WriterListType { unordered, ordered };

struct ltstr
{
  bool operator()(const _SH_String & s1, const _SH_String & s2) const
  {
    return strcmp(s1.cstr(), s2.cstr()) < 0;
  }
};

class WordPerfectCollector : public _SH_DocumentInterface
{
public:
	WordPerfectCollector(_SH_InputStream *pInput, DocumentHandler *pHandler);
	virtual ~WordPerfectCollector();
	bool filter();

	virtual void setDocumentMetaData(const _SH_PropertyList &propList) {};
	virtual void startDocument();
	virtual void endDocument();
	
	virtual void openPageSpan(const _SH_PropertyList &propList);
	virtual void closePageSpan();
	virtual void openHeader(const _SH_PropertyList &propList);
	virtual void closeHeader();
	virtual void openFooter(const _SH_PropertyList &propList);
	virtual void closeFooter();
	virtual void openParagraph(const _SH_PropertyList &propList, const _SH_PropertyListVector &tabStops);
	virtual void closeParagraph();
	virtual void openSpan(const _SH_PropertyList &propList);
	virtual void closeSpan();
	virtual void openSection(const _SH_PropertyList &propList, const _SH_PropertyListVector &columns);
	virtual void closeSection();
	virtual void insertTab();
	virtual void insertText(const _SH_String &text);
 	virtual void insertLineBreak();
	virtual void defineOrderedListLevel(const _SH_PropertyList &propList);
	virtual void defineUnorderedListLevel(const _SH_PropertyList &propList);	
	virtual void openOrderedListLevel(const _SH_PropertyList &propList);
	virtual void openUnorderedListLevel(const _SH_PropertyList &propList);
	virtual void closeOrderedListLevel();
	virtual void closeUnorderedListLevel();
	virtual void openListElement(const _SH_PropertyList &propList, const _SH_PropertyListVector &tabStops);
	virtual void closeListElement();
	virtual void openFootnote(const _SH_PropertyList &propList);
	virtual void closeFootnote();
	virtual void openEndnote(const _SH_PropertyList &propList);
	virtual void closeEndnote();
 	virtual void openTable(const _SH_PropertyList &propList, const _SH_PropertyListVector &columns);
 	virtual void openTableRow(const _SH_PropertyList &propList);
	virtual void closeTableRow();
 	virtual void openTableCell(const _SH_PropertyList &propList);
	virtual void closeTableCell();
	virtual void insertCoveredTableCell(const _SH_PropertyList &propList);
 	virtual void closeTable();

#if defined(HAVE_LIBWPD_090) || defined(HAVE_LIBWPD_0100)
	virtual void definePageStyle(const _SH_PropertyList &propList) {}
	virtual void defineParagraphStyle(const _SH_PropertyList &propList, const _SH_PropertyListVector &tabStops) {}
	virtual void defineCharacterStyle(const _SH_PropertyList &propList) {}
	virtual void defineSectionStyle(const _SH_PropertyList &propList, const _SH_PropertyListVector &columns) {}
	virtual void insertSpace() {}
	virtual void insertField(const _SH_String &type, const _SH_PropertyList &propList) {}
	virtual void openComment(const _SH_PropertyList &propList) {}
	virtual void closeComment() {}
	virtual void openTextBox(const _SH_PropertyList &propList) {}
	virtual void closeTextBox() {}
	virtual void openFrame(const _SH_PropertyList &propList) {}
	virtual void closeFrame() {}
	virtual void insertBinaryObject(const _SH_PropertyList &propList, const _SH_BinaryData &data) {}
	virtual void insertEquation(const _SH_PropertyList &propList, const _SH_String &data) {}
#endif

#if defined(HAVE_LIBWPD_0100)
  virtual void startDocument(const _SH_PropertyList &propList) {}
  virtual void defineEmbeddedFont(const _SH_PropertyList &propList) {}
  virtual void defineParagraphStyle(const _SH_PropertyList &propList) {}
  virtual void openParagraph(const _SH_PropertyList &propList) {}
  virtual void openLink(const _SH_PropertyList &propList) {}
  virtual void closeLink() {}
  virtual void defineSectionStyle(const _SH_PropertyList &propList) {}
  virtual void openSection(const _SH_PropertyList &propList) {}
  virtual void insertField(const _SH_PropertyList &propList) {}
  virtual void openListElement(const _SH_PropertyList &propList) {}
  virtual void openTable(const _SH_PropertyList &propList) {}
	virtual void insertBinaryObject(const _SH_PropertyList &propList) {}
	virtual void insertEquation(const _SH_PropertyList &propList) {}
	virtual void openGroup(const _SH_PropertyList &propList) {}
	virtual void closeGroup() {}
	virtual void defineGraphicStyle(const _SH_PropertyList &propList) {}
	virtual void drawRectangle(const _SH_PropertyList &propList) {}
	virtual void drawEllipse(const _SH_PropertyList &propList) {}
	virtual void drawPolygon(const _SH_PropertyList &propList) {}
	virtual void drawPolyline(const _SH_PropertyList &propList) {}
	virtual void drawPath(const _SH_PropertyList &propList) {}
	virtual void drawConnector(const _SH_PropertyList &propList) {}
#endif

protected:
	void _resetDocumentState();
	bool _parseSourceDocument(_SH_InputStream &input);
	bool _writeTargetDocument(DocumentHandler &xHandler);
	void _writeBegin();
	void _writeDefaultStyles(DocumentHandler &xHandler);
	void _writeMasterPages(DocumentHandler &xHandler);
	void _writePageMasters(DocumentHandler &xHandler);
	void _allocateFontName(const _SH_String &);

private:
	void _openListLevel(TagOpenElement *pListLevelOpenElement);
	void _closeListLevel(const char *szListType);

  _SH_InputStream *mpInput;
  DocumentHandler *mpHandler;
	bool mbUsed; // whether or not it has been before (you can only use me once!)

	WriterDocumentState mWriterDocumentState;

	// paragraph styles
	std::map<_SH_String, ParagraphStyle *, ltstr> mTextStyleHash;

  // span styles
  std::map<_SH_String, SpanStyle *, ltstr> mSpanStyleHash;

	// font styles
	std::map<_SH_String, FontStyle *, ltstr> mFontHash;

	// section styles
	std::vector<SectionStyle *> mSectionStyles;
	float mfSectionSpaceAfter;

	// table styles
	std::vector<TableStyle *> mTableStyles;

	// list styles
	unsigned int miNumListStyles;

	// style elements
	std::vector<DocumentElement *> mStylesElements;
	// content elements
	std::vector<DocumentElement *> mBodyElements;
	// the current set of elements that we're writing to
	std::vector<DocumentElement *> * mpCurrentContentElements;

	// page state
	std::vector<PageSpan *> mPageSpans;
	PageSpan *mpCurrentPageSpan;
	int miNumPageStyles;

	// list styles / state
	ListStyle *mpCurrentListStyle;
	unsigned int miCurrentListLevel;
	unsigned int miLastListLevel;
	unsigned int miLastListNumber;
	std::vector<ListStyle *> mListStyles;
	bool mbListContinueNumbering;
	bool mbListElementOpened;
	bool mbListElementParagraphOpened;

	// table state
	TableStyle *mpCurrentTableStyle;
};
#endif
