/*
  this is the main class of the encoder/decoder
  it has all the methods you need to load/write/convert the bob/bod data
  
  I was inspired by document object model (DOM) from W3C - hence the 
  bob_dom prefix in most of classes
*/

#ifndef BOB_DOM_INCLUDED
#define BOB_DOM_INCLUDED

#include "bob_dom_cut.h"
#include "bob_dom_bob.h"

#include "settings.h"

#include <stdarg.h>

class bob_dom_document
{
	public:
		enum ErrorCode
		{
			// BOB converter
			E_BadHeader,
			E_BadEndHeader,
			E_Error,
			E_NoError,
			E_MoreData,
			E_NotEnoughData,
			E_NoStatFormat,
			E_FormatUserWarning,
			E_UnkPointHeader,
			E_PointNotFound,
			E_BadVersion
		};
		
		enum ErrorSeverity
		{
			S_OK = 0,
			S_Warning,
			S_Error
		};
		
		enum ErrorFacility
		{
			F_BOBLoader,
			F_StatLoader
		};
		
		struct Error
		{
			int code;
			char text[255];
			
			void makeCode(ErrorFacility f, ErrorSeverity s, ErrorCode e)
			{
				code=s << 24;
				code|=f << 16;
				code|=e;
			}
			
			ErrorSeverity severity() const { return (ErrorSeverity)(code >> 24); }
			ErrorFacility facility() const { return (ErrorFacility)((code >> 16) & 0xff); }
			bool failed() const { return (severity() & S_Error) > 0; }
			bool warning() const { return (severity() & S_Warning) > 0; }
			bool succeeded() const { return (severity() & S_OK) == 0; }
			
			ErrorCode getCode() const { return (ErrorCode)(code & 0xFFFF); }
		};
		
	private:
		typedef ext::list<Error*> ErrorList;
		
		const Settings *settings;
		
		void error(ErrorFacility facility, ErrorSeverity severity, ErrorCode code, const char *format, ...);
		void verror(ErrorFacility facility, ErrorSeverity severity, ErrorCode code, const char *format, va_list ap);
		void vbob_error(bob_error_severity severity, bob_error_codes code, const char *format, va_list ap);
		void bob_error(bob_error_severity severity, bob_error_codes code, const char *format, ...);
		void ini_error(Settings::ErrorType type, Settings::ErrorCodes code, const char *msg);
		
	public:
		typedef ErrorList::iterator ErrorIterator;
		
		bob_dom_bob *bob;
		bob_dom_cut *cut;
		ErrorList errors;
		
		bob_dom_document(const Settings *settings) { this->settings=settings; bob=0; cut=0; }
		~bob_dom_document() { delete bob; delete cut; clearErrors(); }
		
		void clearErrors() 
		{ 
			for(ErrorIterator &it=errors.begin(); it!=errors.end(); ++it){
				delete *it;
			}
			errors.clear(); 
		}
		
		bool fromFile(bob_dom_ibinaryfilestream& is);
		
		bool convert(bob_dom_ibinaryfilestream& is, bob_dom_otextfilestream& os);
		
		bool toFile(bob_dom_obinaryfilestream& os);
		bool toFile(bob_dom_otextfilestream& os);
		
};


#endif // !defined(BOB_DOM_INCLUDED)