/* $Id$ */

/**
 * \file 
 * $Revision$
 * $Date$
 * 
 * Copyright (C) 2015 The University of Sydney, Australia
 *
 * This file is part of GPlates.
 *
 * GPlates is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, version 2, as published by
 * the Free Software Foundation.
 *
 * GPlates 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 General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#ifndef GPLATES_PRESENTATION_TRANSCRIBESESSION_H
#define GPLATES_PRESENTATION_TRANSCRIBESESSION_H

#include <utility>
#include <vector>
#include <boost/optional.hpp>
#include <QString>
#include <QStringList>

#include "scribe/ScribeExceptions.h"

#include "utils/CallStackTracker.h"


namespace GPlatesScribe
{
	class Scribe;
}

namespace GPlatesPresentation
{
	namespace TranscribeSession
	{
		/**
		 * Save the session using the specified Scribe.
		 *
		 * The feature collection filenames are returned.
		 * Files with no filename are ignored (i.e. "New Feature Collection"s that only exist in memory).
		 *
		 * If @a scribe_gplates_1_5 is specified then saves the deprecated GPlates 1.5 session state
		 * to it, otherwise combines session state into @a scribe.
		 *
		 * Can throw other exceptions derived in namespace 'GPlatesScribe::Exceptions' if there were
		 * any hard errors (such as incorrectly saving the session, eg, due to not registering a
		 * the polymorphic object type, etc).
		 */
		QStringList
		save(
				GPlatesScribe::Scribe &scribe,
				boost::optional<GPlatesScribe::Scribe &> scribe_gplates_1_5 = boost::none);


		/**
		 * Load the session using the specified Scribe.
		 *
		 * Throws @a UnsupportedVersion exception, on loading, if the transcription is incompatible
		 * (ie, if was generated by a version of GPlates that is either too new or too old).
		 *
		 * Can throw other exceptions derived in namespace 'GPlatesScribe::Exceptions' if there were
		 * any hard errors.
		 *
		 * Any files that were not loaded (either they don't exist or the load failed) get reported
		 * in the read errors dialog.
		 *
		 * Note: @a feature_collection_filenames is required for earlier versions of GPlates that
		 * load the feature collection filenames from the metadata only (ie, not from @a scribe).
		 */
		void
		load(
				GPlatesScribe::Scribe &scribe,
				const QStringList &feature_collection_filenames);


		/**
		 * Exception that's thrown if a session's archive stream (being read) was written using a
		 * version of GPlates that is either too old (no longer supported due to breaking changes
		 * in the way some of GPlates objects are currently transcribed) or too new
		 * (was written using a future version of GPlates that stopped providing backwards
		 * compatibility for the current version).
		 */
		class UnsupportedVersion :
				public GPlatesScribe::Exceptions::BaseException
		{
		public:

			explicit
			UnsupportedVersion(
					const GPlatesUtils::CallStack::Trace &exception_source,
					boost::optional< std::vector<GPlatesUtils::CallStack::Trace> >
							transcribe_incompatible_call_stack = boost::none) :
				GPlatesScribe::Exceptions::BaseException(exception_source),
				d_transcribe_incompatible_call_stack(transcribe_incompatible_call_stack)
			{  }

			~UnsupportedVersion() throw() { }

			//! Returns the transcribe-incompatible call stack trace, if any.
			boost::optional< std::vector<GPlatesUtils::CallStack::Trace> >
			get_transcribe_incompatible_trace() const
			{
				return d_transcribe_incompatible_call_stack;
			}

		protected:

			virtual
			const char *
			exception_name() const
			{
				return "TranscribeSession::UnsupportedVersion";
			}

			virtual
			void
			write_message(
					std::ostream &os) const;

		private:

			boost::optional< std::vector<GPlatesUtils::CallStack::Trace> > d_transcribe_incompatible_call_stack;

		};
	}
}

#endif // GPLATES_PRESENTATION_TRANSCRIBESESSION_H
