/* $Id$
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.etch.bindings.csharp.compiler;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.etch.compiler.Backend;
import org.apache.etch.compiler.CmdLineOptions;
import org.apache.etch.compiler.EtchGrammarConstants;
import org.apache.etch.compiler.LogHandler;
import org.apache.etch.compiler.Output;
import org.apache.etch.compiler.ParseException;
import org.apache.etch.compiler.Token;
import org.apache.etch.compiler.Version;
import org.apache.etch.compiler.ast.Builtin;
import org.apache.etch.compiler.ast.Except;
import org.apache.etch.compiler.ast.Item;
import org.apache.etch.compiler.ast.Message;
import org.apache.etch.compiler.ast.MessageDirection;
import org.apache.etch.compiler.ast.Module;
import org.apache.etch.compiler.ast.MsgDirHelper;
import org.apache.etch.compiler.ast.Name;
import org.apache.etch.compiler.ast.Named;
import org.apache.etch.compiler.ast.ParamList;
import org.apache.etch.compiler.ast.Parameter;
import org.apache.etch.compiler.ast.ReservedWordChecker;
import org.apache.etch.compiler.ast.Service;
import org.apache.etch.compiler.ast.Struct;
import org.apache.etch.compiler.ast.Thrown;
import org.apache.etch.compiler.ast.TypeRef;
import org.apache.etch.compiler.opt.ToString;
import org.apache.etch.compiler.opt.ToString.FieldItem;
import org.apache.etch.compiler.opt.ToString.FmtItem;
import org.apache.etch.compiler.opt.ToString.StringItem;
import org.apache.etch.util.Assertion;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.log.LogChute;


/**
 * Compiler is a helper class not only for Backend, but also for the templates.
 * They call methods here to perform "hard" tasks.
 */
public class Compiler extends Backend
{
	private final static String tmplPath1 = "org/apache/etch/bindings/csharp/compiler/";

	private final static String tmplPath2 = "resources/org/apache/etch/bindings/csharp/compiler/";

	private final static String fnSuffix = ".cs";

	private final static String VERSION = Version.VERSION + " / "
		+ CompilerVersion.VERSION;

	/**
	 * Constructs the Compiler. This is a helper class not only for Backend, but
	 * also for the templates. They call methods here to perform "hard" tasks.
	 *
	 * @throws Exception
	 */
	public Compiler() throws Exception
	{
		initVelocity();
		
		String[] path = { tmplPath1, tmplPath2 };
		vf_vm = getTemplate( path, "vf.vm" );
		intf_vm = getTemplate( path, "intf.vm" );
		remote_vm = getTemplate( path, "remote.vm" );
		stub_vm = getTemplate( path, "stub.vm" );
		helper_vm = getTemplate( path, "helper.vm" );
		readme_vm = getTemplate( path, "readme.vm" );
		main_vm = getTemplate( path, "main.vm" );
		base_vm = getTemplate( path, "base.vm" );
		impl_vm = getTemplate( path, "impl.vm" );

		local_kwd = getPath( path, "csharpKeywords.kwd" );
	}

	private final Template vf_vm;

	private final Template intf_vm;

	private final Template remote_vm;

	private final Template stub_vm;

	private final Template helper_vm;

	private final Template readme_vm;

	private final Template main_vm;

	private final Template base_vm;

	private final Template impl_vm;

	private final String local_kwd;

	private LogHandler lh;
	
	/**
	 * Initializes use of velocity engine and sets up
	 * resource loaders.
	 * @throws Exception
	 */
	private void initVelocity()
		throws Exception
	{
		Velocity.setProperty( Velocity.RUNTIME_LOG_LOGSYSTEM, new MyLogger() );
		
		Velocity.setProperty( Velocity.RESOURCE_LOADER, "file, class" );

		Velocity.setProperty( "file.resource.loader.description", "Velocity File Resource Loader" );
		Velocity.setProperty( "file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader" );
		Velocity.setProperty( "file.resource.loader.path", "." );

		Velocity.setProperty( "class.resource.loader.description", "Velocity Classpath Resource Loader" );
		Velocity.setProperty( "class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader" );
		
		Velocity.init();
	}
	
	private static class MyLogger implements LogChute
	{
		private final LogHandler lh = null;
		
		public void init( RuntimeServices rts ) throws Exception
		{
			// ignore.
		}

		public boolean isLevelEnabled( int level )
		{
			return level >= 2;
		}

		public void log( int level, String msg )
		{
			if (level < 2)
				return;
			
			if (lh != null)
				lh.report( level == 2 ? LogHandler.LEVEL_WARNING : LogHandler.LEVEL_ERROR, null, msg );
			else
				System.out.printf( "Velocity msg (%d): %s\n", level, msg );
		}

		public void log( int level, String msg, Throwable e )
		{
			if (level < 2)
				return;
			
			if (lh != null)
				lh.report( level == 2 ? LogHandler.LEVEL_WARNING : LogHandler.LEVEL_ERROR, null, msg );
			else
				System.out.printf( "Velocity msg (%d): %s: %s\n", level, msg, e );
		}
	}

	/**
	 * @param path
	 * @param fn
	 * @return the velocity template
	 * @throws Exception
	 */
	private Template getTemplate( String[] path, String fn )
		throws Exception
	{
		ResourceNotFoundException rnfe = null;
		
		for (String p: path)
		{
			if (p == null)
				continue;
			
//			System.out.println( "trying to load template "+(p+fn) );
			try
			{
				if (Velocity.resourceExists( p+fn ))
					return Velocity.getTemplate( p+fn );
			}
			catch ( ResourceNotFoundException e )
			{
				rnfe = e;
			}
			catch ( Exception e )
			{
				System.out.println( "ignoring "+e);
			}
		}
		
		if (rnfe != null)
			throw rnfe;
		
		throw new ResourceNotFoundException("could not find resource: "+fn);
	}

	@Override
	public void generate( Module module, CmdLineOptions options )
		throws Exception
	{
		lh = options.lh;

		boolean ignoreGlobal = options.ignoreGlobalWordsList;
		boolean ignoreLocal = options.ignoreLocalWordsList;
		String userWords = options.userWordsList != null ? options.userWordsList.getPath() : null;
		Set<String> what = options.what;

		// Load the reserved words lists if any have been provided.
		Map<String, String> words = new HashMap<String, String>();
		if (!ignoreGlobal)
			mapWords( global_kwd, words );
		if (!ignoreLocal)
			mapWords( local_kwd, words );
		if (userWords != null)
			mapWords( userWords, words );

		// check for collisions with the reserved word list.
		ReservedWordChecker checker = new ReservedWordChecker( words, false, lh );
		module.treewalk( checker );
		if (!checker.ok())
		{
			lh.report( LogHandler.LEVEL_ERROR, null, "Encountered errors during java generation." );
			return;
		}

		// ok, we're ready to generate code. make sure the
		// output directories exist.

		Output dir = options.output;
		Output templateDir = options.templateOutput;
		
		String m = module.name().name;
		if (m.length() > 0)
		{
			dir = dir.newPackage( m );
			templateDir = templateDir.newPackage( m );
		}
		
		// generate code for each service.

		for (Service intf : module)
		{
			generate( intf, what, dir, templateDir );
		}
	}

	private void generate( final Service intf, Set<String> what, Output dir,
		Output templateDir ) throws Exception
	{
		what = populateWhat( what );

		if (what.isEmpty())
		{
			// lh.logMessage( lh.LEVEL_ERROR, null, "User has selected NONE\n" );
			return;
		}

		final MessageDirection msgDir = getMessageDirection( what );

		if (what.contains( WHAT_INTF ))
		{
			// Generate the value factory file.
			
			generateVf( intf, dir );
	
			// Generate the interface, remote, and stub files.
	
			generateIntfRemoteStub( intf, dir, msgDir, MessageDirection.BOTH, false );
	
			generateIntfRemoteStub( intf, dir, msgDir, MessageDirection.SERVER, true );
	
			generateIntfRemoteStub( intf, dir, msgDir, MessageDirection.CLIENT, true );
	
			// Generate helper file.
	
			generateHelper( intf, dir, msgDir );
			
			// Generate base file.
			
			generateBase( intf, dir, msgDir );
	
			// Generate readme file.
			
			generateReadme( intf, dir, msgDir );
		}

		// Generate main template file.

		if (what.contains( WHAT_MAIN ))
			generateMain( intf, templateDir, msgDir );

		// Generate impl template file.

		if (what.contains( WHAT_IMPL ))
			generateImpl( intf, templateDir, msgDir );
	}

	private void generateReadme( final Service intf, Output dir,
		final MessageDirection msgDir ) throws Exception
	{
		doFile( dir, "readme-etch-csharp-files.txt", lh, new Gen()
		{
			public void run( PrintWriter pw ) throws Exception
			{
				generateReadme( pw, intf, msgDir );
			}
		} );
	}

	private void generateVf( final Service intf, Output dir )
		throws Exception
	{
		doFile( dir, getVfName( intf ) + fnSuffix, lh, new Gen()
		{
			public void run( PrintWriter pw ) throws Exception
			{
				generateVf( pw, intf );
			}
		} );
	}

	private void generateHelper( final Service intf, Output dir,
		final MessageDirection msgDir ) throws Exception
	{
		doFile( dir, getHelperName( intf ) + fnSuffix, lh, new Gen()
		{
			public void run( PrintWriter pw ) throws Exception
			{
				generateHelper( pw, intf, msgDir );
			}
		} );
	}

	private void generateMain( final Service intf, Output dir,
		MessageDirection msgDir ) throws Exception
	{
		if (msgDir == MessageDirection.BOTH
				|| msgDir == MessageDirection.CLIENT)
			doFile( dir, getMainName( intf, MessageDirection.CLIENT ) + fnSuffix, lh, new Gen()
			{
				public void run( PrintWriter pw ) throws Exception
				{
					generateMain( pw, intf, MessageDirection.CLIENT, false );
				}
			} );

		if (msgDir == MessageDirection.BOTH
				|| msgDir == MessageDirection.SERVER)
			doFile( dir, getMainName( intf, MessageDirection.SERVER ) + fnSuffix, lh, new Gen()
			{
				public void run( PrintWriter pw ) throws Exception
				{
					generateMain( pw, intf, MessageDirection.SERVER, false );
				}
			} );
	}

	private void generateBase( final Service intf, Output dir,
		MessageDirection msgDir ) throws Exception
	{
		if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.CLIENT)
			doFile( dir, getBaseName( intf, MessageDirection.CLIENT ) + fnSuffix, lh, new Gen()
			{
				public void run( PrintWriter pw ) throws Exception
				{
					generateBase (pw, intf, MessageDirection.CLIENT, false );
				}
			} );

		if (msgDir == MessageDirection.BOTH || msgDir == MessageDirection.SERVER)
			doFile( dir, getBaseName( intf, MessageDirection.SERVER ) + fnSuffix, lh, new Gen()
			{
				public void run( PrintWriter pw ) throws Exception
				{
					generateBase (pw, intf, MessageDirection.SERVER, false );
				}
			} );
	}

	private void generateImpl( final Service intf, Output dir,
		MessageDirection msgDir ) throws Exception
	{
		if (msgDir == MessageDirection.BOTH
				|| msgDir == MessageDirection.CLIENT)
			doFile( dir, getImplName( intf, MessageDirection.CLIENT ) + fnSuffix, lh, new Gen()
			{
				public void run( PrintWriter pw ) throws Exception
				{
					generateImpl( pw, intf, MessageDirection.CLIENT, false );
				}
			} );

		if (msgDir == MessageDirection.BOTH
				|| msgDir == MessageDirection.SERVER)
			doFile( dir, getImplName( intf, MessageDirection.SERVER ) + fnSuffix, lh, new Gen()
			{
				public void run( PrintWriter pw ) throws Exception
				{
					generateImpl( pw, intf, MessageDirection.SERVER, false );
				}
			} );
	}

	private void generateIntfRemoteStub( final Service intf, Output dir,
		final MessageDirection what, final MessageDirection mc,
		final boolean hasBaseClass ) throws Exception
	{
		// Generate interface file

		doFile( dir, getIntfName( intf, mc ) + fnSuffix, lh, new Gen()
		{
			public void run( PrintWriter pw ) throws Exception
			{
				generateIntf( pw, intf, mc, hasBaseClass );
			}
		} );

		// Generate remote file

		if (mc == MessageDirection.BOTH || what == MessageDirection.BOTH
				|| mc != what)
			doFile( dir, getRemoteName( intf, mc ) + fnSuffix, lh, new Gen()
			{
				public void run( PrintWriter pw ) throws Exception
				{
					generateRemote( pw, intf, mc, hasBaseClass );
				}
			} );

		// Generate stub file

		if (mc == MessageDirection.BOTH || what == MessageDirection.BOTH
				|| mc == what)
			doFile( dir, getStubName( intf, mc ) + fnSuffix, lh, new Gen()
			{
				public void run( PrintWriter pw ) throws Exception
				{
					generateStub( pw, intf, mc, hasBaseClass );
				}
			} );
	}

	/**
	 * Generate the value factory for the service.
	 *
	 * @param pw
	 * @param intf
	 * @throws Exception
	 */
	void generateVf( PrintWriter pw, Service intf ) throws Exception
	{
		// params keeps track of the total set of parameters
		// named (for enums, structs, exceptions, and messages).
		Set<String> params = new HashSet<String>();

		VelocityContext context = new VelocityContext();
		context.put( "now", new Date() );
		context.put( "version", VERSION );
		context.put( "helper", this );
		context.put( "intf", intf );
		context.put( "params", params );
		vf_vm.merge( context, pw );
	}

	/**
	 * Generate the interface for the service.
	 *
	 * @param pw
	 * @param intf
	 * @param mc
	 * @param hasBaseClass
	 * @throws Exception
	 */
	void generateIntf( PrintWriter pw, Service intf, MessageDirection mc,
		boolean hasBaseClass ) throws Exception
	{
		VelocityContext context = new VelocityContext();
		context.put( "now", new Date() );
		context.put( "version", VERSION );
		context.put( "helper", this );
		context.put( "intf", intf );
		context.put( "mc", mc );
		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
		context.put( "hasBaseClass", hasBaseClass );
		intf_vm.merge( context, pw );
	}

	/**
	 * Generate the call to message implementation of the interface. This class
	 * turns calls on its methods into messages which are sent to the remote
	 * stub. For two-way calls, it then waits for a response message, returning
	 * the result therein to the caller.
	 *
	 * @param pw
	 * @param intf
	 * @param mc
	 * @param hasBaseClass
	 * @throws Exception
	 */
	void generateRemote( PrintWriter pw, Service intf, MessageDirection mc,
		boolean hasBaseClass ) throws Exception
	{
		VelocityContext context = new VelocityContext();
		context.put( "now", new Date() );
		context.put( "version", VERSION );
		context.put( "helper", this );
		context.put( "intf", intf );
		context.put( "mc", mc );
		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
		context.put( "hasBaseClass", hasBaseClass );
		context.put( "methodList", new ArrayList<String>());
		remote_vm.merge( context, pw );
	}

	/**
	 * Generate the message to call implementation. This class accepts a message
	 * and turns it back into a call on the user's implementation. For two-way
	 * messages, the return value from the user's implementation method is turned
	 * into the appropriate response message and sent.
	 *
	 * @param pw
	 * @param intf
	 * @param mc
	 * @param hasBaseClass
	 * @throws Exception
	 */
	void generateStub( PrintWriter pw, Service intf, MessageDirection mc,
		boolean hasBaseClass ) throws Exception
	{
		VelocityContext context = new VelocityContext();
		context.put( "now", new Date() );
		context.put( "version", VERSION );
		context.put( "helper", this );
		context.put( "intf", intf );
		context.put( "mc", mc );
		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
		context.put( "hasBaseClass", hasBaseClass );
		stub_vm.merge( context, pw );
	}

	/**
	 * Generate the transport plumbing helper.
	 *
	 * @param pw
	 * @param intf
	 * @param mc
	 * @throws Exception
	 */
	void generateHelper( PrintWriter pw, Service intf, MessageDirection mc )
		throws Exception
	{
		VelocityContext context = new VelocityContext();
		context.put( "now", new Date() );
		context.put( "version", VERSION );
		context.put( "helper", this );
		context.put( "intf", intf );
		context.put( "mc", mc );

		helper_vm.merge( context, pw );
	}

	/**
	 * Generate the readme.txt.
	 *
	 * @param pw
	 * @param intf
	 * @param mc
	 * @throws Exception
	 */
	void generateReadme( PrintWriter pw, Service intf, MessageDirection mc ) throws Exception
	{
		VelocityContext context = new VelocityContext();
		context.put( "now", new Date() );
		context.put( "version", VERSION );
		context.put( "helper", this );
		context.put( "intf", intf );
		context.put( "mc", mc );

		readme_vm.merge( context, pw );
	}

	/**
	 * Generate the template main program.
	 *
	 * @param pw
	 * @param intf
	 * @param mc
	 * @param hasBaseClass
	 * @throws Exception
	 */
	void generateMain( PrintWriter pw, Service intf, MessageDirection mc,
		boolean hasBaseClass ) throws Exception
	{
		VelocityContext context = new VelocityContext();
		context.put( "now", new Date() );
		context.put( "version", VERSION );
		context.put( "helper", this );
		context.put( "intf", intf );
		context.put( "mc", mc );
		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
		context.put( "hasBaseClass", hasBaseClass );
		main_vm.merge( context, pw );
	}

	/**
	 * Generates the base implementation of the interfaces, with each
	 * method throwing an exception to the tune that it isn't implemented.
	 * User's impl will extend this base implementation.
	 * @param pw
	 * @param intf
	 * @param mc
	 * @param hasBaseClass
	 * @throws Exception
	 */
	void generateBase( PrintWriter pw, Service intf, MessageDirection mc,
		boolean hasBaseClass ) throws Exception
		{
			VelocityContext context = new VelocityContext();
			context.put( "now", new Date() );
			context.put( "version", VERSION );
			context.put( "helper", this );
			context.put( "intf", intf );
			context.put( "mc", mc );
			context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
			context.put( "hasBaseClass", hasBaseClass );
			context.put( "methodList", new ArrayList<String>());
			base_vm.merge( context, pw );
		}

	/**
	 * Generate the template user implemention class which extends the base
	 * implementation generated above. This class will only have the appropriate
	 * constructor and reference to the appropriate remote, and a comment inviting
	 * the user to override methods.
	 * @param pw
	 * @param intf
	 * @param mc
	 * @param hasBaseClass
	 * @throws Exception
	 */
	void generateImpl( PrintWriter pw, Service intf, MessageDirection mc,
		boolean hasBaseClass ) throws Exception
	{
		VelocityContext context = new VelocityContext();
		context.put( "now", new Date() );
		context.put( "version", VERSION );
		context.put( "helper", this );
		context.put( "intf", intf );
		context.put( "mc", mc );
		context.put( "suffix", MsgDirHelper.getSuffix( mc ) );
		context.put( "hasBaseClass", hasBaseClass );
		impl_vm.merge( context, pw );
	}

	private String getVfName( Service intf )
	{
		return "ValueFactory" + getIntfName( intf, MessageDirection.BOTH );
	}

	private String getIntfName( Service intf, MessageDirection mc )
	{
		String suffix = MsgDirHelper.getSuffix( mc );
		return intf.name() + suffix;
	}

	private String getMainName( Service intf, MessageDirection mc )
	{
		if (mc == MessageDirection.SERVER)
			return "Main" + intf.name() + "Listener";
		return "Main" + getIntfName( intf, mc );
	}

	private String getImplName( Service intf, MessageDirection mc )
	{
		return "Impl" + getIntfName( intf, mc );
	}

	private String getRemoteName( Service intf, MessageDirection mc )
	{
		return "Remote" + getIntfName( intf, mc );
	}

	private String getStubName( Service intf, MessageDirection mc )
	{
		return "Stub" + getIntfName( intf, mc );
	}

	private String getHelperName( Service intf )
	{
		return intf.name() + "Helper";
	}
	
	private String getBaseName( Service intf, MessageDirection mc )
	{
		return "Base" + getIntfName( intf, mc );
	}

	@Override
	public String asyncReceiverPoolName( Message msg )
	{
		return msg.getAsyncReceiver().toString().toLowerCase();
	}

	@Override
	public String getTypeValue( TypeRef type, Token value )
	{
		// System.out.println( "getTypeValue called with: "+type+": "+value );
		Token t = type.type();
		switch (t.kind)
		{
			case EtchGrammarConstants.LONG:
				return value.image + "L";
			case EtchGrammarConstants.FLOAT:
				return value.image + "F";
			case EtchGrammarConstants.DOUBLE:
				return value.image + "D";
			case EtchGrammarConstants.STRING:
				return protectString( value.image );
			default:
				return value.image;
		}
	}

	private String protectString( String s )
	{
		// System.out.println( "protectString called with: "+s );

		StringBuffer sb = new StringBuffer();
		sb.append( "\"" );
		for (char c : s.toCharArray())
		{
			if (c == '\t')
			{
				sb.append( "\\t" );
				continue;
			}
			if (c == '\r')
			{
				sb.append( "\\r" );
				continue;
			}
			if (c == '\n')
			{
				sb.append( "\\n" );
				continue;
			}
			if (c == '\"')
			{
				sb.append( "\\\"" );
				continue;
			}
			if (c == '\\')
			{
				sb.append( "\\\\" );
				continue;
			}
			if (c >= 32 && c < 127)
			{
				sb.append( c );
				continue;
			}
			sb.append( String.format( "\\u%04x", (int) c ) );
		}
		sb.append( "\"" );
		return sb.toString();
	}

	/**
	 * @param type
	 * @return type name appropriate for use as a structure element or exception
	 * parameter or function parameter or result.
	 */
	@Override
	public String getTypeName( TypeRef type )
	{
		if (type.dim() > 0)
			return getNativeTypeName( type ) + dim2spec( type.dim() );
		return getRefTypeName( type );
	}

	/**
	 * @param type the etch type
	 * @return the fundamental native type for java. so etch int -> csharp int,
	 * while etch string -> csharp string.
	 */
	@Override
	public String getNativeTypeName( TypeRef type )
	{
		Token t = type.type();
		switch (t.kind)
		{
			case EtchGrammarConstants.VOID:
				return "void";
			case EtchGrammarConstants.BOOLEAN:
				return "bool";
			case EtchGrammarConstants.BYTE:
				return "sbyte";
			case EtchGrammarConstants.SHORT:
				return "short";
			case EtchGrammarConstants.INT:
				return "int";
			case EtchGrammarConstants.LONG:
				return "long";
			case EtchGrammarConstants.FLOAT:
				return "float";
			case EtchGrammarConstants.DOUBLE:
				return "double";
			case EtchGrammarConstants.STRING:
				return "string";
			case EtchGrammarConstants.OBJECT:
				return "Object";
			default:
			{
				// we have to use a fully qualified name here.
				// find the actual type...
				Named<?> n = type.intf().get( t.image );
				if (n == null)
					throw new IllegalArgumentException( String.format(
						"undefined or ambiguous name at line %d: %s",
						t.beginLine, t.image ) );
				return n.efqname( this );
			}
		}
	}

	/**
	 * @param type the etch type
	 * @return the fundamental native reference type for java. so etch int ->
	 * csharp int?, while etch string -> csharp string.
	 */
	private String getRefTypeName( TypeRef type )
	{
		Token t = type.type();
		switch (t.kind)
		{
			case EtchGrammarConstants.VOID:
				return "void";
			case EtchGrammarConstants.BOOLEAN:
				return "bool?";
			case EtchGrammarConstants.BYTE:
				return "sbyte?";
			case EtchGrammarConstants.SHORT:
				return "short?";
			case EtchGrammarConstants.INT:
				return "int?";
			case EtchGrammarConstants.LONG:
				return "long?";
			case EtchGrammarConstants.FLOAT:
				return "float?";
			case EtchGrammarConstants.DOUBLE:
				return "double?";
			case EtchGrammarConstants.STRING:
				return "string";
			case EtchGrammarConstants.OBJECT:
				return "Object";
			default:
			{
				// we have to use a fully qualified name here.
				// find the actual type...
				Named<?> n = type.intf().get( t.image );
				if (n == null)
					throw new IllegalArgumentException( String.format(
						"undefined or ambiguous name at line %d: %s",
						t.beginLine, t.image ) );
				if (n.isEnumx())
					return n.efqname( this ) + "?";
				return n.efqname( this );
			}
		}
	}

	private String dim2spec( int i )
	{
		String s = "";
		while (i-- > 0)
			s += "[]";
		return s;
	}

	@Override
	public String formatString( ParamList<Service> n, boolean isExcept )
		throws ParseException, IOException
	{
		ToString ts = (ToString) n.getOpt( "ToString" );
		List<FmtItem> list;
		if (ts != null)
		{
			list = ts.getFormat();
			n.checkFormatList( ts.lineno(), list );
		}
		else if (isExcept)
		{
			list = n.mkFormatList( true, ((Except)n).hasExtends() );
			// Temp Fix :remove once Scott fixes the ParamList code
			modifyFormatList(list,true);
		}
		else
		{
			list = n.mkFormatList( false, ((Struct)n).hasExtends() );
//			 Temp Fix :remove once Scott fixes the ParamList code
			modifyFormatList(list,false);
		}


		if (list.size() == 1)
		{
			return list.get( 0 ).value();
		}

		StringBuffer sb = new StringBuffer();
		sb.append( "String.Format( " );
		sb.append( "\"" );
		int j = 0;
		for (FmtItem i : list)
		{
			if (i instanceof FieldItem)
			{
				sb.append( "{" + j + "}" );
				j++;
			}
			else
			{
				escape( sb, ((StringItem) i).value() );
			}
		}
		j = 0;

		sb.append( "\"" );
		for (FmtItem i : list)
		{
			if (i instanceof FieldItem)
			{
				sb.append( ", " );
				sb.append( ((FieldItem) i).value() );
			}
		}
		sb.append( " )" );
		return sb.toString();
	}

	private void escape( StringBuffer sb, String s ) throws IOException
	{
		StringReader rdr = new StringReader( s );
		int c;
		while ((c = rdr.read()) >= 0)
		{
			if (c == '"')
				sb.append( "\\\"" );
			else if (c == '\\')
				sb.append( "\\\\" );
			else if (c == '\t')
				sb.append( "\\t" );
			else if (c == '\r')
				sb.append( "\\r" );
			else if (c == '\n')
				sb.append( "\\n" );
			else
				sb.append( (char) c );
		}
	}

	@Override
	public String mfvname( String vname )
	{
		return "_mf_" + vname;
	}

	@Override
	public String mtvname( String vname )
	{
		return "_mt_" + vname;
	}

	@Override
	public String getLang()
	{
		return "csharp";
	}

	@Override
	public String enum_efqname( String fqname, String moduleName,
		String serviceName, String enumName )
	{

//		return moduleName + "." + "Consts" + serviceName + "." + enumName;
		return moduleName + "." + "types" + "." + serviceName + "." + enumName;

	}

	@Override
	public String except_efqname( String fqname, String moduleName,
		String serviceName, String exceptName )
	{

//		return moduleName + "." + "Consts" + serviceName + "." + exceptName;
		return moduleName + "." + "types" + "." + serviceName + "." + exceptName;
	}

	@Override
	public String struct_efqname( String fqname, String moduleName,
		String serviceName, String structName )
	{

//		return moduleName + "." + "Consts" + serviceName + "." + structName;
		return moduleName + "." + "types" + "." + serviceName + "." + structName;
	}

	@Override
	public String qualifyParameterName( Token name )
	{
		return name.image;
	}

	@Override
	public String qualifyConstantName( Service intf, Token name )
	{
		String moduleName = intf.parent().name().name;
		String serviceName = intf.name().name;
		return moduleName + "." + "types" + "." + serviceName + "." + "Consts" + serviceName + "." + name.image;
	}

	@Override
	public String qualifyEnumName( Service intf, Token name )
	{
		String moduleName = intf.parent().name().name;
		String serviceName = intf.name().name;
		return moduleName + "." + "types" + "." + serviceName + "." +  name.image;
	}

	@Override
	public String getValidator( Named<?> named )
	{
		if (named instanceof Parameter)
		{
			Parameter param = (Parameter) named;
			TypeRef type = param.type();

			if (type.isBuiltin())
				return "Validator_" + type.type() + ".Get( " + type.dim()
					+ " )";

			Named<?> n = type.getNamed( type.intf() );

			if (n.isBuiltin())
			{
				Builtin b = (Builtin) n;
				String cn = b.className();
				if (cn.endsWith( "?" ))
					cn = cn.substring( 0, cn.length()-1 );
				
				return String.format( "Validator_custom.Get( typeof(%s), %d, %s )",
					cn, type.dim(), b.allowSubclass() );
			}

			// Allow subclassing for etch defined structs and externs.

			if (n.isStruct() || n.isExcept())
				return String.format( "Validator_custom.Get( typeof(%s), %d, true )",
					n.efqname( this ), type.dim() );

			// Don't allow subclassing for externs or etch defined enums.

			if (!(n.isExtern() || n.isEnumx()))
				Assertion.check( n.isExtern() || n.isEnumx(),
					"n.isExtern() || n.isEnumx(): "+n );

			return "Validator_custom.Get( typeof ( "
				+ n.efqname( this )  + " ), " + type.dim()
				+ ", false )";
		}

		if (named instanceof Thrown)
		{
			Thrown thrown = (Thrown) named;
			Except e = (Except) thrown.getNamed();
			return "Validator_custom.Get( typeof ( " + e.efqname( this )
				+ " ) , 0,true )";
		}

		if (named instanceof Item)
			return "Validator_boolean.Get( 0 )";

		return "null";
	}

	/**
	 * @param name
	 * @return the appropriate name for a getter method.
	 */
	public String getGetterName( Name name )
	{
		String s = name.name;
		return "Get" + s.substring( 0, 1 ).toUpperCase()+s.substring( 1 );
	}

	/**
	 * @param name
	 * @return the appropriate name for a setter method.
	 */
	public String getSetterName( Name name )
	{
		String s = name.name;
		return "Set" + s.substring( 0, 1 ).toUpperCase()+s.substring( 1 );
	}

	private void modifyFormatList(List<FmtItem> list,boolean isException) {
		for(int i=0;i<list.size();i++) {
			FmtItem item = list.get( i );

			if (item.value().contains( "super.getMessage()" )) {
				list.remove( i );
				list.add(i, new FieldItem(  "base.GetMessage()" ) );
			}
			if (item.value().contains( "super.toString()" )) {
				list.remove( i );
				list.add(i, new FieldItem(  "base.ToString()" ) );
			}
		}
	}

	@Override
	public void addDefaults( Service service ) throws ParseException
	{
		addBuiltin( service, newName( "List" ), "System.Collections.IList", true );
		addBuiltin( service, newName( "Map" ), "System.Collections.IDictionary", true );
		addBuiltin( service, newName( "Set" ), "System.Collections.Hashtable", true );
		addBuiltin( service, newName( "Datetime" ), "System.DateTime?", false );
	}
}
