/*
 * Copyright (c) 2010 Remko Tronçon
 * Licensed under the GNU General Public License v3.
 * See Documentation/Licenses/GPLv3.txt for more information.
 */

#pragma once

#include "Swiften/Elements/Form.h"
#include "Swiften/Parser/GenericPayloadParser.h"

namespace Swift {
	class FormParser : public GenericPayloadParser<Form> {
		public:
			FormParser();

			virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
			virtual void handleEndElement(const String& element, const String&);
			virtual void handleCharacterData(const String& data);

		private:
			class FieldParseHelper {
				public:
					virtual ~FieldParseHelper() {}
					virtual void addValue(const String&) = 0;
					virtual boost::shared_ptr<FormField> getField() const {
						return field;
					}
				protected:
					boost::shared_ptr<FormField> field;
			};
			class BoolFieldParseHelper : public FieldParseHelper {
					virtual void addValue(const String& s) {
						boost::dynamic_pointer_cast< GenericFormField<bool> >(getField())->setValue(s == "1" || s == "true");
						getField()->addRawValue(s);
					}
			};
			class StringFieldParseHelper : public FieldParseHelper {
					virtual void addValue(const String& s) {
						boost::shared_ptr<GenericFormField<String> > field = boost::dynamic_pointer_cast< GenericFormField<String> >(getField());
						if (field->getValue().isEmpty()) {
							field->setValue(s);
						}
						else {
							field->setValue(field->getValue() + "\n" + s);
						}
						getField()->addRawValue(s);
					}
			};
			class JIDFieldParseHelper : public FieldParseHelper {
					virtual void addValue(const String& s) {
						boost::dynamic_pointer_cast< GenericFormField<JID> >(getField())->setValue(JID(s));
					}
			};
			class StringListFieldParseHelper : public FieldParseHelper {
					virtual void addValue(const String& s) {
						// FIXME: Inefficient, but too much hassle to do efficiently
						boost::shared_ptr<GenericFormField< std::vector<String> > > field = boost::dynamic_pointer_cast< GenericFormField<std::vector<String > > >(getField());
						std::vector<String> l = field->getValue();
						l.push_back(s);
						field->setValue(l);
						getField()->addRawValue(s);
					}
			};
			class JIDListFieldParseHelper : public FieldParseHelper {
					virtual void addValue(const String& s) {
						// FIXME: Inefficient, but too much hassle to do efficiently
						boost::shared_ptr< GenericFormField< std::vector<JID> > > field = boost::dynamic_pointer_cast< GenericFormField<std::vector<JID > > >(getField());
						std::vector<JID> l = field->getValue();
						l.push_back(JID(s));
						field->setValue(l);
						getField()->addRawValue(s);
					}
			};
			
#define SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(name, baseParser) \
	class name##FormFieldParseHelper : public baseParser##FieldParseHelper { \
		public: \
			typedef boost::shared_ptr<name##FormFieldParseHelper> ref; \
			static ref create() { \
				return ref(new name##FormFieldParseHelper()); \
			} \
		private: \
			name##FormFieldParseHelper() : baseParser##FieldParseHelper() { \
				field = name##FormField::create(); \
			} \
	};

			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Boolean, Bool);
			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Fixed, String);
			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Hidden, String);
			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(ListSingle, String);
			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(TextMulti, String);
			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(TextPrivate, String);
			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(TextSingle, String);
			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(JIDSingle, JID);
			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(JIDMulti, JIDList);
			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(ListMulti, StringList);
			SWIFTEN_DECLARE_FORM_FIELD_PARSE_HELPER(Untyped, StringList);

			enum Level { 
				TopLevel = 0, 
				PayloadLevel = 1,
				FieldLevel = 2
			};
			int level_;
			String currentText_;
			String currentOptionLabel_;
			boost::shared_ptr<FieldParseHelper> currentFieldParseHelper_;
	};
}