#include <ascript.h>

namespace AScript {

//-----------------------------------------------------------------------------
// Main entry
//-----------------------------------------------------------------------------
int MainW(int argc, const char *argv[])
{
	Signal sig;
	static const Option::Info optInfoTbl[] = {
		{ "help",			'h', false	},
		{ "import",			'i', true	},
		{ "import-dir",		'I', true	},
		{ "command",		'c', true	},
		{ "directory",		'C', true	},
		{ "quiet",			'q', false	},
		{ "version",		'v', false	},
	};
	Option opt(optInfoTbl, NUMBEROF(optInfoTbl));
	bool rtn = opt.Parse(sig, argc, argv);
	if (!rtn) {
		//::fprintf(stderr, "%s\n", sig.GetErrString().c_str());
		return 1;
	}
	if (opt.IsSet("version")) {
		//PrintVersion(stderr);
		return 0;
	}
	if (opt.IsSet("help")) {
		//PrintVersion(stderr);
		//PrintHelp(stderr);
		return 0;
	}
	if (opt.IsSet("directory")) {
		OAL::ChangeCurDir(opt.GetString("directory", ""));
	}
	EnvironmentRoot env(argc, argv);
	Stream *pConsole = env.GetConsole(false);
	if (opt.IsSet("import-dir")) {
		env.AddModuleSearchPath(sig, opt.GetStringList("import-dir"));
	}
	if (opt.IsSet("import")) {
		foreach_const (StringList, pModuleNames, opt.GetStringList("import")) {
			if (!env.ImportModules(sig, pModuleNames->c_str())) {
				pConsole->PrintSignal(sig, sig);
				return 1;
			}
		}
	}
	if (opt.IsSet("command")) {
		foreach_const (StringList, pCmd, opt.GetStringList("command")) {
			const char *cmd = pCmd->c_str();
			if (::strcmp(cmd, "") == 0) continue;
			Expr *pExpr = Parser().ParseString(env, sig, "<command line>", cmd);
			if (sig.IsSignalled()) {
				pConsole->PrintSignal(sig, sig);
				return 1;
			}
			if (pExpr == NULL) {
				pConsole->Println(sig, "incomplete command");
			} else {
				Value result = pExpr->Exec(env, sig);
				if (sig.IsSignalled()) {
					pConsole->PrintSignal(sig, sig);
					return 1;
				} else if (result.IsValid()) {
					pConsole->Println(sig, result.ToString(sig).c_str());
				}
			}
		}
	}
	Expr *pExprRoot = NULL;
	if (argc >= 2) {
		pExprRoot = Parser().ParseStream(env, sig, argv[1]);
		if (sig.IsSignalled()) {
			pConsole->PrintSignal(sig, sig);
			return 1;
		}
		pExprRoot->Exec(env, sig);
		if (sig.IsSignalled()) {
			pConsole->PrintSignal(sig, sig);
			sig.ClearSignal();
		}
	}
	Expr::Delete(pExprRoot);
	return 0;
}

#if 0
void PrintVersion(FILE *fp)
{
	::fprintf(fp, "%s\n", GetOpening());
}

void PrintHelp(FILE *fp)
{
	::fprintf(fp,
"usage: ascript [option] [file] [arg] ...\n"
"available options:\n"
"-h             print this help\n"
"-i module[,..] import module(s) before parsing\n"
"-I dir         specify a directory to search for modules\n"
"-c cmd         execute program from command line\n"
"-C dir         change directory before executing scripts\n"
"-v             print version string\n"
	);
}
#endif

}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
											LPSTR lpCmdLine, int nCmdShow)
{
	return AScript::MainW(__argc, const_cast<const char **>(__argv));
}
