/* -*- 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-2003 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."
 */

#ifndef _FRAME_HXX_
#define _FRAME_HXX_

#include <stack>
#include <vector>

#include <librvngabw/librvngabw.hxx>

// for std::shared_ptr
#include "DocumentElement.hxx"
#include "FilterInternal.hxx"

namespace librvngabw
{
/** class used to store a frame properties and/or contents
 */
class Frame
{
public:
	//! the different anchor
	enum AnchorType
	{
		A_Page, A_Section, A_Frame, A_Paragraph, A_Char, A_CharBaseLine, A_Cell
	};
	//! the AbiWord anchor
	enum AnchorToUse
	{
		U_Page=0, U_Column, U_Block, U_Cell,
		U_NumberAnchorToUse // do not remove
	};
	//! constructor
	Frame(const librevenge::RVNGPropertyList &xPropList, int xId);
	//! destructor
	virtual ~Frame();
	//! returns true if the frame is opened
	bool isOpened() const
	{
		return m_isOpened;
	}
	//! set the opened flag
	void setOpened(bool open)
	{
		m_isOpened=open;
	}
	//! returns true if the frame content is empty and the storage was never asked for
	bool isEmpty() const
	{
		return m_frameType.empty() && m_imageName.empty();
	}
	//! set the frame type
	void setFrameType(char const *frameType)
	{
		if (frameType)
			m_frameType="textbox";
	}
	//! set the background image
	void setBackgroundImage(librevenge::RVNGString const &image)
	{
		m_imageName=image;
	}
	//! returns the frame storage
	DocumentElementVector &getStorage(char const *frameType)
	{
		if (!m_frameType.empty() || !frameType)// force text box
			m_frameType="textbox";
		else
			m_frameType=frameType;
		return m_content;
	}

	//! returns the anchor (or A_Page if unknown)
	AnchorType getAnchorType() const
	{
		return m_anchor;
	}
	//! returns the anchor to be used
	AnchorToUse getAnchorToUse() const
	{
		switch (m_anchor)
		{
		case A_Page:
			return U_Page;
		case A_Frame:
		case A_Section:
			return U_Column;
		case A_Paragraph:
		case A_Char:
		case A_CharBaseLine:
		case A_Cell:
		default:
			return U_Block;
		}
	}
	//! returns the frame's page or -1 is the frame is not on a page
	int getPageNumber() const
	{
		return m_anchor==A_Page ? m_pageNumber : -1;
	}
	//! add frame content
	void write(DocumentElementVector &storage, const librevenge::RVNGPropertyList &propExtra) const;
	//! add the size dimension to a property list
	void addDimensionsTo(librevenge::RVNGPropertyList &propList) const;

private:
	//! a flag to know if the frame is opened
	bool m_isOpened;
	//! the frame property list
	librevenge::RVNGPropertyList m_propList;
	//! the abiword id
	int m_xId;
	//! the frame type if known
	librevenge::RVNGString m_frameType;
	//! the image name if it exists
	librevenge::RVNGString m_imageName;
	//! the anchor
	AnchorType m_anchor;
	//! the page ( if m_anchor==A_Page)
	int m_pageNumber;
	//! the frame content (if anchor is page or section)
	DocumentElementVector m_content;
	// disable copying
	Frame(const Frame &);
	Frame &operator=(const Frame &);
};

/** a manager to keep the list of frame */
class FrameManager
{
public:
	//! constructor
	FrameManager();
	//! destructor
	virtual ~FrameManager();
	//! clean all data
	void clean();
	//! returns true if a frame is opened
	bool isFrameOpened() const
	{
		return !m_openedFrameStack.empty();
	}
	//! returns the actual frame
	std::shared_ptr<Frame> getActualFrame()
	{
		if (m_openedFrameStack.empty()) return std::shared_ptr<Frame>();
		return m_openedFrameStack.top();
	}
	//! returns the actual frame ( const function )
	std::shared_ptr<Frame const> getActualFrame() const
	{
		if (m_openedFrameStack.empty()) return std::shared_ptr<Frame const>();
		return m_openedFrameStack.top();
	}
	//! open a frame and update the list of opened frame
	std::shared_ptr<Frame> openFrame(const librevenge::RVNGPropertyList &xPropList, int &xId);
	//! close a frame and update the list of opened frame
	bool closeFrame();
	//! add all frame contents which correspond to an anchor
	void writeContents(DocumentElementVector &storage, Frame::AnchorToUse anchor);

private:
	//! the list of frames
	std::vector<std::shared_ptr<Frame> > m_frameList;
	//! the stack of actual opened frames
	std::stack<std::shared_ptr<Frame> > m_openedFrameStack;
	//! flags to know if we have some frames to send
	bool m_notSentFrameByAnchor[Frame::U_NumberAnchorToUse];
	// disable copying
	FrameManager(const FrameManager &);
	FrameManager &operator=(const FrameManager &);
};
}

#endif

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