/*
  things used both in bob_dom_cut and bob_dom_bob are defined here
*/

#ifndef BOB_DOM_BASE_INCLUDED
#define BOB_DOM_BASE_INCLUDED

#include "../common/ext_list.h"
#include "bob_names.h"

#include "bob_dom_stream.h"
#include "bob_dom_filestream.h"

#include <string.h>
#include <stdarg.h>

class bob_dom_section;
class bob_dom_string;
class bob_dom_info;

enum bob_error_codes
{
	e_noError,
	e_badHeader,
	e_badEndHeader,
	e_notEnoughData,
	e_moreData,
	e_unkPointHeader,
	e_error,
	e_format_noStatFormat,
	e_format_notEnoughData,
	e_format_UserWarning,
	e_pointNotFound,
	e_badVersion,
	e_unsupportedFrameFlags,
	e_unkMaterialValueType
};

enum bob_error_severity
{
	s_warning,
	s_error
};

const char* bob_traslate_error(bob_error_codes code);
int peek(bob_dom_ibinaryfilestream& is);

class bob_with_errors
{
	protected:
		void error(bob_error_codes code);
		void error(bob_error_severity severity, bob_error_codes code);
		void error(bob_error_codes code, const char *format, ...);
		void error(bob_error_severity severity, bob_error_codes code, const char *format, ...);
		void verror(bob_error_severity severity, bob_error_codes code, const char *format, va_list ap);
		
	public:
		struct bob_error
		{
			bob_error_codes code;
			bob_error_severity severity;
			char text[255];
		};
		
		typedef ext::list<bob_error*> ErrorList;
		typedef ext::list<bob_error*>::iterator ErrorIterator;
		
		ErrorList errors;
		
		virtual ~bob_with_errors()
		{
			for(ErrorIterator &it=errors.begin(); it!=errors.end(); it++){
				delete *it;
			}
		}
};

class bob_dom_section : public bob_with_errors
{
	public:
		static const null_value=-1;
		
		int peek(bob_dom_ibinaryfilestream& is)
		{
			int i;
			is >> i;
			is.advance(-(int)sizeof(int));
			return i;
		}
};

template <class Ty>
class bob_dom_cantainer
{
	private:
		typedef ext::list<Ty*> list_type;
	
	public:
		typedef Ty value_type;
		typedef Ty* value_type_ptr;
		typedef value_type child_type;
		typedef typename list_type::size_type size_type;
		typedef typename list_type::iterator iterator;
		typedef typename list_type::const_iterator const_iterator;
		
	protected:
		list_type children;
	
	public:
		const_iterator begin() const { return children.begin(); }
		iterator begin() { return children.begin(); }
		const_iterator end() const { return children.end(); }
		iterator end() { return children.end(); }
		
		virtual ~bob_dom_cantainer()
		{
			removeChildren();
		}
		
		void removeChildren()
		{
			for(iterator &it=children.begin(); it!=children.end(); ++it){
				delete *it;
			}
			children.clear();
		}
		
		size_type size() const { return children.size(); }
		
		value_type_ptr createChild() { return *(children.push_back(new value_type())); }
		
		value_type_ptr front() { return children.front(); }
		value_type_ptr back() { return children.back(); }
		
		void removeChild(iterator &where) 
		{
			delete *where;
			children.erase(where);
		}
		
		void removeChild(value_type_ptr child) 
		{
			iterator it, old;
			while((it=children.find(child))!=children.end()){
				old=it - 1;
				delete *it;
				children.erase(it);
				it=old;
			}
		}
};

class bob_dom_string : public bob_dom_section
{
	public:
		char *m_text;
		
		const char *text() const { return m_text; }
		void text(const char *str) { text(str, strlen(str));	}
		void text(const char *str, size_t size) 
		{
			delete[] m_text;
			m_text=new char[size + 1];
			memcpy(m_text, str, size);
			m_text[size]=0;
		}
		
		bob_dom_string() { m_text=0; }
		virtual ~bob_dom_string() { delete[] m_text; }
		
		bool load(bob_dom_ibinaryfilestream& is, int startHeader, int endHeader);
		bool toFile(bob_dom_obinaryfilestream& os, int begin, int end);
};

class bob_dom_info : public bob_dom_string
{
	public:
		static const hdr_begin=BOB_SECTION_NAME_INFO_BEGIN;
		static const hdr_end=BOB_SECTION_NAME_INFO_END;
		
		bool load(bob_dom_ibinaryfilestream& is) { return bob_dom_string::load(is, hdr_begin, hdr_end); }
		bool toFile(bob_dom_obinaryfilestream& os) { return bob_dom_string::toFile(os, hdr_begin, hdr_end); }
		bool toFile(bob_dom_otextfilestream& os);
};

#endif // !defined(BOB_DOM_BASE_INCLUDED)