/* Dialect - Code Output Formatter
 * Copyright (C) 2001-2002  Jay Freeman (saurik)
*/

/*
 *        Redistribution and use in source and binary
 * forms, with or without modification, are permitted
 * provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the
 *    above copyright notice, this list of conditions
 *    and the following disclaimer in the documentation
 *    and/or other materials provided with the
 *    distribution.
 * 3. The name of the author may not be used to endorse
 *    or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef DIALECT_CSHARPDIALECT_H
#define DIALECT_CSHARPDIALECT_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "dialect/dialect.h"
#include "dialect/IDialect.h"
#include "dialect/DialectImpl.h"
#include "ilengineer/Operation.h"
#include "ilengineer/Ops/MSIL/Call.h"

namespace Dialect {

	DIAPEXIS_CLASS CSharpDialect :
		public DialectImpl<IDialect>
	{

		DIAPEXIS_OBJECT(CSharpDialect)

		DIAPEXIS_QUERY_BEGIN(CSharpDialect)
        DIAPEXIS_QUERY_MAP(Diapexis::Unknown)
		DIAPEXIS_QUERY_MAP(IDialect)
		DIAPEXIS_QUERY_END()

	  public:
		CSharpDialect() {}

		using DialectImpl<IDialect>::Render;
		void Render(const Metallurgy::Value *value, std::wstring &builder);

		void Perform(const Metallurgy::Element *element, std::wstring &builder, Metallurgy::ModDeque &mods);
		void Formulate(Metallurgy::Property *property);
		void Formulate(Metallurgy::Method *method);
		void Formulate(const std::wstring &str);
		void Formulate(wchar_t chr);
		void Formulate(ILEngineer::Operation *op);
		void Formulate(ILEngineer::Statement *st);
		void Formulate(Metallurgy::Attribute *attr);
		void Formulate(const Metallurgy::TypeDef &type);

		void Formulate(const Metallurgy::Element *element) {
			std::wstring builder;
			Render(element, builder);
			*wout << builder;
		}

		void PrintOperator(ILEngineer::Ops::MSIL::Call *call);

		/*void Formulate(Metallurgy::MetaMethod &method);
		void Formulate(const Metallurgy::MetaElement &element);
		void Formulate(ILEngineer::Operation *op);
		void Formulate(ILEngineer::Statement *st);
		void Formulate(const std::wstring &str);
		void Formulate(Metallurgy::MetaProperty &property);
		void Formulate(Metallurgy::Attribute &attr);*/

		void Formulate(Metallurgy::Field &field) {
			*wout << GetIndent();

			switch (field.getAccess()) {
				case Chordata::Flags::fdPublic:
					*wout << L"public ";
					break;
				case Chordata::Flags::fdPrivate:
					*wout << L"private ";
					break;
				case Chordata::Flags::fdFamily:
					*wout << L"protected ";
					break;
			}

			if (field.IsStatic())
				*wout << L"static ";

			Formulate(field.getElement());
			*wout << L' ' << field.getName().getFull() << L';' << std::endl;
		}
	};

}

#endif//DIALECT_CSHARPDIALECT_H