/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* librvngabw
 * Version: MPL 2.0 / LGPLv2.1+
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Major Contributor(s):
 * Copyright (C) 2002-2004 William Lachance (wrlach@gmail.com)
 * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch)
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms
 * of the GNU Lesser General Public License Version 2.1 or later
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
 * applicable instead of those above.
 *
 * For further information visit http://libwpd.sourceforge.net
 */

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

#include <librevenge/librevenge.h>

#include <map>
#include <stack>
#include <sstream>
#include <string>

#include <librvngabw/librvngabw.hxx>

#include "DocumentElement.hxx"
#include "FilterInternal.hxx"

#include "ListStyle.hxx"
#include "PageSpan.hxx"
#include "Table.hxx"

#include "ABWGenerator.hxx"

namespace librvngabw
{

class ABWSpreadsheetToTableGeneratorPrivate
{
public:
	//! constructor
	explicit ABWSpreadsheetToTableGeneratorPrivate(ABWGenerator &generator) :
		m_ABWGenerator(generator), m_generatorStorage(generator.getCurrentStorage()),
		m_isStartDocumentSeen(false), m_isFirstSpreadsheetSeen(false), m_isInChart(false), m_isInHeaderFooter(false)
	{
		m_ABWGenerator.pushStorage(&getDummyStorage());
	}
	//! destructor
	~ABWSpreadsheetToTableGeneratorPrivate()
	{
		m_ABWGenerator.popStorage();
	}

	//! returns the curren xId
	int &getXId()
	{
		return m_ABWGenerator.m_xId;
	}

	//
	// storage
	//
	//! returns the current storage
	DocumentElementVector *getCurrentStorage() const
	{
		return m_ABWGenerator.getCurrentStorage();
	}
	//! returns the dummy data storage
	DocumentElementVector &getDummyStorage()
	{
		return m_ABWGenerator.getDummyStorage();
	}

	//! push a storage
	void pushStorage(DocumentElementVector *newStorage)
	{
		m_ABWGenerator.pushStorage(newStorage);
	}
	/** pop a storage */
	bool popStorage()
	{
		return m_ABWGenerator.popStorage();
	}

	// page, header/footer, master page

	//! returns if we are in a master page
	bool inHeaderFooter() const
	{
		return m_isInHeaderFooter;
	}


	//
	// list function
	//

	//! return the page span manager
	ListManager &getListManager()
	{
		return m_ABWGenerator.m_listManager;
	}
	/// pop the list state (if possible)
	void popListState()
	{
		m_ABWGenerator.m_listManager.popState();
	}
	/// push the list state by adding an empty value
	void pushListState()
	{
		m_ABWGenerator.m_listManager.pushState();
	}

	//
	// note
	//

	/// returns true if we are in a note or an annotation
	bool inNoteOrInAnnotation() const
	{
		auto const &state=getState();
		return state.m_isInNote || state.m_isInAnnotation;
	}

	//
	// frame/table
	//

	//! returns the frame manager
	FrameManager &getFrameManager()
	{
		return m_ABWGenerator.m_frameManager;
	}

	//! returns the table manager
	TableManager &getTableManager()
	{
		return m_ABWGenerator.m_tableManager;
	}

	//
	// state gestion
	//

	//! returns the actual state
	ABWGenerator::State &getState()
	{
		return m_ABWGenerator.getState();
	}
	//! returns the actual state
	ABWGenerator::State const &getState() const
	{
		return m_ABWGenerator.getState();
	}
	//! push a state
	void pushState()
	{
		m_ABWGenerator.pushState();
	}
	//! pop a state
	void popState()
	{
		m_ABWGenerator.popState();
	}
	//! the main document generator
	ABWGenerator &m_ABWGenerator;
	//! the original generator storage
	DocumentElementVector *m_generatorStorage;
	//! a flag to know if the document has been started
	bool m_isStartDocumentSeen;
	//! a flag to know if we have seen the first spreadsheet
	bool m_isFirstSpreadsheetSeen;
	//! a flag to know if we are in a chart zone
	bool m_isInChart;
	//! a flag to know if we are in a header/footer zone
	bool m_isInHeaderFooter;

private:
	ABWSpreadsheetToTableGeneratorPrivate(const ABWSpreadsheetToTableGeneratorPrivate &);
	ABWSpreadsheetToTableGeneratorPrivate &operator=(const ABWSpreadsheetToTableGeneratorPrivate &);
};

ABWSpreadsheetToTableGenerator::ABWSpreadsheetToTableGenerator(ABWGenerator &generator) :
	m_data(new ABWSpreadsheetToTableGeneratorPrivate(generator))
{
}

ABWSpreadsheetToTableGenerator::~ABWSpreadsheetToTableGenerator()
{
	if (m_data)
		delete m_data;
}

void ABWSpreadsheetToTableGenerator::setDocumentMetaData(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::defineEmbeddedFont(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::openPageSpan(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::closePageSpan()
{
}

void ABWSpreadsheetToTableGenerator::defineSheetNumberingStyle(const librevenge::RVNGPropertyList &/*propList*/)
{
	// TODO
}

void ABWSpreadsheetToTableGenerator::openSheet(const librevenge::RVNGPropertyList &propList)
{
	auto const &state=m_data->getState();
	m_data->pushState();
	if (m_data->m_isInChart || m_data->m_isInHeaderFooter ||
	        state.m_isInFrame || m_data->inNoteOrInAnnotation() ||
	        m_data->m_isFirstSpreadsheetSeen)
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::openSheet can not open a spreadsheet!!!\n"));
		return;
	}
	auto table=m_data->getTableManager().openTable(propList, m_data->getXId(), true);
	if (!table)
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::openSheet: can not open a spreadsheet\n"));
		return;
	}
	m_data->m_isFirstSpreadsheetSeen=m_data->getState().m_isSheetOpened=true;
	m_data->pushStorage(table->getStorage());
}

void ABWSpreadsheetToTableGenerator::closeSheet()
{
	auto const &state=m_data->getState();
	m_data->popState();
	if (!state.m_isSheetOpened)
		return;
	m_data->popStorage();
	auto table=m_data->getTableManager().getActualTable();
	if (!table)
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::closeSheet: can not find the spreadsheet\n"));
		return;
	}
	table->checkTable();
	table->write(*m_data->m_generatorStorage);
	m_data->getTableManager().closeTable();
}

void ABWSpreadsheetToTableGenerator::openSheetRow(const librevenge::RVNGPropertyList &propList)
{
	if (m_data->inNoteOrInAnnotation() || !m_data->getTableManager().getActualTable())
		return;
	m_data->getTableManager().getActualTable()->openRow(propList);
}

void ABWSpreadsheetToTableGenerator::closeSheetRow()
{
	if (m_data->inNoteOrInAnnotation() || !m_data->getTableManager().getActualTable())
		return;
	m_data->getTableManager().getActualTable()->closeRow();
}

void ABWSpreadsheetToTableGenerator::openSheetCell(const librevenge::RVNGPropertyList &propList)
{
	std::shared_ptr<Table> table=m_data->getTableManager().getActualTable();
	if (m_data->inNoteOrInAnnotation() || !table)
		return;

	m_data->getState().m_isTableCellOpened = table->openCell(propList);
	if (m_data->getState().m_isTableCellOpened)
		m_data->pushStorage(table->getStorage());
}

void ABWSpreadsheetToTableGenerator::closeSheetCell()
{
	if (m_data->inNoteOrInAnnotation())
		return;
	if (m_data->getState().m_isTableCellOpened && m_data->getTableManager().getActualTable())
	{
		m_data->getTableManager().getActualTable()->closeCell();
		m_data->popStorage();
	}
	m_data->getState().m_isTableCellOpened=false;
}

void ABWSpreadsheetToTableGenerator::defineChartStyle(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::openChart(const librevenge::RVNGPropertyList &)
{
	if (m_data->m_isInChart)
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::openHeader: can not open a chart\n"));
		return;
	}
	m_data->m_isInChart=true;
	m_data->pushStorage(&m_data->getDummyStorage());
}

void ABWSpreadsheetToTableGenerator::closeChart()
{
	if (!m_data->m_isInChart)
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::closeChart: no chart is already opened\n"));
		return;
	}
	m_data->m_isInChart=false;
	m_data->popStorage();
}

void ABWSpreadsheetToTableGenerator::openChartPlotArea(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::closeChartPlotArea()
{
}

void ABWSpreadsheetToTableGenerator::openChartTextObject(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::closeChartTextObject()
{
}

void ABWSpreadsheetToTableGenerator::insertChartAxis(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::openChartSerie(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::closeChartSerie()
{
}

void ABWSpreadsheetToTableGenerator::openHeader(const librevenge::RVNGPropertyList &)
{
	if (m_data->inHeaderFooter())
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::openHeader: can not open a header\n"));
		return;
	}
	m_data->m_isInHeaderFooter=true;
	m_data->pushStorage(&m_data->getDummyStorage());
}

void ABWSpreadsheetToTableGenerator::closeHeader()
{
	if (!m_data->inHeaderFooter())
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::closeHeader: no header/footer is already opened\n"));
		return;
	}
	m_data->m_isInHeaderFooter=false;
	m_data->popStorage();
}

void ABWSpreadsheetToTableGenerator::openFooter(const librevenge::RVNGPropertyList &)
{
	if (m_data->inHeaderFooter())
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::openFooter: can not open a footer\n"));
		return;
	}
	m_data->m_isInHeaderFooter=true;
	m_data->pushStorage(&m_data->getDummyStorage());
}

void ABWSpreadsheetToTableGenerator::closeFooter()
{
	if (!m_data->inHeaderFooter())
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::closeFooter: no header/footer is already opened\n"));
		return;
	}
	m_data->m_isInHeaderFooter=false;
	m_data->popStorage();
}

void ABWSpreadsheetToTableGenerator::openSection(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::closeSection()
{
}

void ABWSpreadsheetToTableGenerator::defineParagraphStyle(const librevenge::RVNGPropertyList &propList)
{
	m_data->m_ABWGenerator.defineParagraphStyle(propList);
}

void ABWSpreadsheetToTableGenerator::openParagraph(const librevenge::RVNGPropertyList &propList)
{
	m_data->m_ABWGenerator.openParagraph(propList);

	m_data->pushState();
	m_data->getState().m_paragraphOpenedAtCurrentLevel=true;
}

void ABWSpreadsheetToTableGenerator::closeParagraph()
{
	if (!m_data->getState().m_paragraphOpenedAtCurrentLevel)
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::closeParagraph: can not find any opened paragraph\n"));
		return;
	}
	m_data->m_ABWGenerator.closeParagraph();
	m_data->popState();
}

void ABWSpreadsheetToTableGenerator::defineCharacterStyle(const librevenge::RVNGPropertyList &propList)
{
	m_data->m_ABWGenerator.defineCharacterStyle(propList);
}

void ABWSpreadsheetToTableGenerator::openSpan(const librevenge::RVNGPropertyList &propList)
{
	m_data->m_ABWGenerator.openSpan(propList);
}

void ABWSpreadsheetToTableGenerator::closeSpan()
{
	m_data->m_ABWGenerator.closeSpan();
}

void ABWSpreadsheetToTableGenerator::openLink(const librevenge::RVNGPropertyList &propList)
{
	m_data->m_ABWGenerator.openLink(propList);
}

void ABWSpreadsheetToTableGenerator::closeLink()
{
	m_data->m_ABWGenerator.closeLink();
}


void ABWSpreadsheetToTableGenerator::openOrderedListLevel(const librevenge::RVNGPropertyList &propList)
{
	m_data->getListManager().openLevel(propList, true);
}

void ABWSpreadsheetToTableGenerator::openUnorderedListLevel(const librevenge::RVNGPropertyList &propList)
{
	m_data->getListManager().openLevel(propList, false);
}

void ABWSpreadsheetToTableGenerator::closeOrderedListLevel()
{
	m_data->getListManager().closeLevel();
}

void ABWSpreadsheetToTableGenerator::closeUnorderedListLevel()
{
	m_data->getListManager().closeLevel();
}

void ABWSpreadsheetToTableGenerator::openListElement(const librevenge::RVNGPropertyList &propList)
{
	if (!m_data->getListManager().openListElement(propList, *m_data->getCurrentStorage(), m_data->getXId()))
		return;

	m_data->pushState();
	m_data->getState().m_listElementOpenedAtCurrentLevel=true;
}

void ABWSpreadsheetToTableGenerator::closeListElement()
{
	auto const &state=m_data->getState();
	if (!state.m_listElementOpenedAtCurrentLevel)
	{
		RVNGABW_DEBUG_MSG(("ABWTextGenerator::closeListElement: can not find any opened paragraph\n"));
		return;
	}
	m_data->getListManager().closeListElement(*m_data->getCurrentStorage());
	m_data->popState();
}

void ABWSpreadsheetToTableGenerator::openFootnote(const librevenge::RVNGPropertyList &propList)
{
	m_data->pushListState();
	m_data->m_ABWGenerator.openNote(propList, true);
}

void ABWSpreadsheetToTableGenerator::closeFootnote()
{
	m_data->m_ABWGenerator.closeNote(true);
	m_data->popListState();
}

void ABWSpreadsheetToTableGenerator::openComment(const librevenge::RVNGPropertyList &propList)
{
	m_data->pushListState();
	m_data->m_ABWGenerator.openAnnotation(propList);
}

void ABWSpreadsheetToTableGenerator::closeComment()
{
	m_data->m_ABWGenerator.closeAnnotation();
	m_data->popListState();
}

void ABWSpreadsheetToTableGenerator::openTable(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::closeTable()
{
}

void ABWSpreadsheetToTableGenerator::openTableRow(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::closeTableRow()
{
}

void ABWSpreadsheetToTableGenerator::openTableCell(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::closeTableCell()
{
}

void ABWSpreadsheetToTableGenerator::insertCoveredTableCell(const librevenge::RVNGPropertyList &)
{
}


void ABWSpreadsheetToTableGenerator::insertTab()
{
	librevenge::RVNGString tab;
	tab.append(0x9);
	m_data->getCurrentStorage()->push_back(std::make_shared<TextElement>(tab));
}

void ABWSpreadsheetToTableGenerator::insertSpace()
{
	m_data->getCurrentStorage()->push_back(std::make_shared<TextElement>(" "));
}

void ABWSpreadsheetToTableGenerator::insertLineBreak()
{
	m_data->getCurrentStorage()->push_back(std::make_shared<TagOpenElement>("br"));
	m_data->getCurrentStorage()->push_back(std::make_shared<TagCloseElement>("br"));
}

void ABWSpreadsheetToTableGenerator::insertField(const librevenge::RVNGPropertyList &propList)
{
	m_data->m_ABWGenerator.insertField(propList);
}

void ABWSpreadsheetToTableGenerator::insertText(const librevenge::RVNGString &text)
{
	if (text.empty()) return;
	m_data->getCurrentStorage()->push_back(std::make_shared<TextElement>(text));
}

void ABWSpreadsheetToTableGenerator::openFrame(const librevenge::RVNGPropertyList &propList)
{
	std::shared_ptr<Frame> frame;
	if (propList["table:end-cell-address"] && m_data->getState().m_isTableCellOpened)
		frame=m_data->getFrameManager().openFrame(propList, m_data->getXId());

	m_data->pushState();
	m_data->pushListState();
	m_data->getState().m_isInFrame=true;

	if (frame)
		m_data->pushStorage(m_data->getCurrentStorage());
	else
		m_data->pushStorage(&m_data->getDummyStorage());
}

void ABWSpreadsheetToTableGenerator::closeFrame()
{
	if (!m_data->getState().m_isInFrame)
		return;

	auto frame=m_data->getFrameManager().getActualFrame();
	if (frame)
		m_data->getFrameManager().closeFrame();
	m_data->popListState();
	m_data->popState();
	m_data->popStorage();
}

void ABWSpreadsheetToTableGenerator::insertBinaryObject(const librevenge::RVNGPropertyList &propList)
{
	if (m_data->getState().m_isInFrame && m_data->getFrameManager().getActualFrame())
		m_data->m_ABWGenerator.insertBinaryObject(propList);
}

void ABWSpreadsheetToTableGenerator::openTextBox(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::closeTextBox()
{
}

void ABWSpreadsheetToTableGenerator::startDocument(const librevenge::RVNGPropertyList &)
{
	if (m_data->m_isStartDocumentSeen)
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::startDocument: document already started\n"));
		return;
	}
	m_data->m_isStartDocumentSeen=true;
}

void ABWSpreadsheetToTableGenerator::endDocument()
{
	if (!m_data->m_isStartDocumentSeen)
	{
		RVNGABW_DEBUG_MSG(("ABWSpreadsheetToTableGenerator::endDocument: document not started\n"));
		return;
	}
}


void ABWSpreadsheetToTableGenerator::openGroup(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::closeGroup()
{
}

void ABWSpreadsheetToTableGenerator::defineGraphicStyle(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::drawRectangle(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::drawEllipse(const librevenge::RVNGPropertyList &)
{
}


void ABWSpreadsheetToTableGenerator::drawPolygon(const librevenge::RVNGPropertyList &)
{
}


void ABWSpreadsheetToTableGenerator::drawPolyline(const librevenge::RVNGPropertyList &)
{
}


void ABWSpreadsheetToTableGenerator::drawPath(const librevenge::RVNGPropertyList &)
{
}

void ABWSpreadsheetToTableGenerator::drawConnector(const librevenge::RVNGPropertyList &)
{
}

}
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
