// Goldie: GOLD Engine for D
// Tools: StaticLang: Generate Static Goldie Language Interface
// Written in the D programming language.

module tools.staticlang.cmd;

import std.array;
import std.path;
import std.stdio;
import std.string;

import semitwist.cmdlineparser;
import semitwist.util.all;

import goldie.all;
import tools.util;

string goldiePackageDir;
static this()
{
	goldiePackageDir = rel2abs(getExecPath()~"../src/goldie/");
}

class CmdArgs
{
	mixin(getter!(bool, "shouldExit"));

	public this(string[] args)
	{
		init();
		shouldExit = !parse(args);
	}
	
	// Direct command-line args (may be baked, not guaranteed to be raw)
	public bool   help;
	public bool   detailhelp;
	public string cgtFile;
	public string outputPackage;
	public string outputDir;

	// Generated
	public string shortPackage; // The last part of the package name
	public string cgtFileOnly;

	// Private ------
	private CmdLineParser cmd;
	
	private void init()
	{
		cmd = new CmdLineParser();
		mixin(defineArg!(cmd, "help",   help,          ArgFlag.Optional, "Displays a help summary and exits" ));
		mixin(defineArg!(cmd, "detail", detailhelp,    ArgFlag.Optional, "Displays a detailed help message and exits" ));
		mixin(defineArg!(cmd, "",       cgtFile,       ArgFlag.Required, "CGT language file to use" ));
		mixin(defineArg!(cmd, "pack",   outputPackage, ArgFlag.Optional, "Name of output package (default: goldie.staticlang.{cgt})" ));
		mixin(defineArg!(cmd, "dir",    outputDir,     ArgFlag.Optional, "Directory of package root (default: current directory)" ));
	}
	
	// Returns: Should processing proceed? If false, the program should exit.
	private bool parse(string[] args)
	{
		enum info =
			helpInfoHeader("StaticLang", "2009-2011 Nick Sabalausky") ~
			"\n\n" ~
			"Generates static Goldie language interface.";
			
		enum sampleUsageMsg = `
			Sample Usage:
			  goldie-staticlang langs/lang.cgt
			      Creates "goldie/staticlang/lang/*.d", each
			      containing "module goldie.staticlang.lang.*;"
			
			  goldie-staticlang langs/lang.cgt -dir:foo/src -pack:myapp.mylang
			      Creates "foo/src/myapp/mylang/*.d", each
			      containing "module myapp.mylang.*;"
		`.normalize();
		
		cmd.parse(args);
		if(detailhelp)
		{
			writeln(info);
			writeln();
			writeln(sampleUsageMsg);
			write(cmd.getDetailedUsage());
			return false;
		}
		if(!cmd.success || help)
		{
			writeln(info);
			writeln();
			writeln(sampleUsageMsg);
			writeln();
			write(cmd.getUsage(13));
			if(!help)
			{
				writeln();
				write(cmd.errorMsg);
			}
			return false;
		}
		
		cgtFileOnly = cgtFile.basename();
		
		if(outputPackage == "")
		{
			shortPackage = cgtFile.getName();
			outputPackage = "goldie.staticlang."~shortPackage;
		}
		else
		{
			uint i = outputPackage.locatePrior('.');

			if(i == outputPackage.length-1)
				outputPackage = outputPackage[0..$-1];
				
			if(i == outputPackage.length)
				shortPackage = outputPackage;
			else
				shortPackage = outputPackage[i+1..$];
			
			//TODO: Ensure shortPackage (and outputPackage) is a valid ident
		}
		
		//TODO*: Make sure this check still works
		if(outputDir == "")
			outputDir = ".";
		outputDir = rel2abs(outputDir);
		outputDir = outputDir~pathSep~replace(outputPackage, ".", pathSep)~pathSep;
		
		//mixin(traceVal!("outputDir       "));
		//mixin(traceVal!("goldiePackageDir"));

		if(outputDir == goldiePackageDir)
		{
			writeln("Error: Output directory is the same as Goldie's package source.");
			writeln("This is disallowed in order to prevent overwriting Goldie's source.");
			writeln("Please set a different output directory.");
			return 1;
		}
		//outputDir = fpOut.native.toString() ~ pathSep;

		return true;
	}
}
