/*
 *  ADP (Another Data Processor) www.adp.la
 *  Copyright (C) 2010 Katsuhisa Ohfuji <katsuhisa@ohfuji.name>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA 02110-1301, USA.
 */
#include <fstream>
#include <iostream>
#include <iterator>
#include "adp.h"

// 定数
#ifdef ___X64____
#define VERSION_TEXT		"ADP Ver 0.81.0251 X64 (http://www.adp.la/)\nCopyright (C) 2010-2012 Katsuhisa Ohfuji. This progman is distributed under GPL.\n"
#else
#if _WIN32
#define VERSION_TEXT		"ADP Ver 0.81.0251 x86 (http://www.adp.la/)\nCopyright (C) 2010-2012 Katsuhisa Ohfuji. This progman is distributed under GPL.\n"
#else
#define VERSION_TEXT		"ADP Ver 0.81.0251 (http://www.adp.la/)\nCopyright (C) 2010-2012 Katsuhisa Ohfuji. This progman is distributed under GPL.\n"
#endif
#endif

int main(int argc, char *argv[], char **envp)
{
	clock_t c = clock();
	time_t	t = time(0);
#ifdef _WIN32
	#ifndef _STLP_DEBUG 
		_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
		_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE); 
		_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR);
		_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE); 
		_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR);
		_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE); 
		_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR);
	#endif
	{
	WSADATA				wsaData;
    WSAStartup( 0x0101, &wsaData);
	}
#endif

	GlobalContext	adp;
	init_gc();
	set_gc(&adp);
		
	MyLogClear("pipe");
	
	argvector.clear();
	convertssmap( envp, envmap);
	getqueryvalue(query);
	getcookievalue(cookies);

	myrand();	// mt乱数シードの初期化
	pzero.value = 0;
	ptrue.value = -1;
	global = 0;
	session = 0;
	sessionid.clear();
	sessionpath.clear();
	sessionwriteflg = false;
	ssmap::iterator i = cookies.find(string(ADP_SESSION_ID_STRING));
	if ( i != cookies.end() ) {
		sessionid = i->second;
		session = getSession(sessionid, sessionpath);
	} else {
		i = envmap.find(string(ADP_SESSION_ID_STRING));
		if ( i != envmap.end() ) {
			sessionid = i->second;
			session = getSession(sessionid, sessionpath);
		} else {
			session = 0;
		}
	}
	default_quote_s = '`';
	default_quote_e = '`';

	first_print = true;
	compiletrace = false;
	dispwarn = false;
	syntaxcheck = false;
	thread_count = 0;
	init_ExecContext_Factory_Map();
	init_awpescapetags();
	bool	printTime = false;
	bool	printTimeClock = false;
	bool	printTimeTime = false;
	bool	printSessionID = false;
	bool	chdirflg = false;


	// ADP_APPLICATION_PATHの読み込み（ライブラリの読み込み）
	bool compile_application = false;
	if ( envmap.find( string("ADP_APPLICATION_PATH")) != envmap.end()  ) {
		string apppath = envmap[string("ADP_APPLICATION_PATH")];
		adp.compile(apppath, false);
	}

	if ( argc < 2 || envmap.find( string("PATH_TRANSLATED")) != envmap.end() ) {
		if ( envmap.find( string("PATH_TRANSLATED")) != envmap.end() ) {
			header_string = "Content-Type: text/html\r\n";
			#ifdef _WIN32
			_setmode(_fileno(stdout), _O_BINARY);
			#endif
			string ppath = envmap[string("PATH_TRANSLATED")];
			string::reverse_iterator ri = find( ppath.rbegin(), ppath.rend(), pseparator);
			if ( ri != ppath.rend() ) {
				first_src_base_path = string( ppath.begin(), ri.base());
				string appath = first_src_base_path + APPLICATIN_GLOBAL;
				adp.compile(appath, true, false);
			}
			chdirflg = true;
			adp.compile(ppath, true, true);
		} else {
			fputs( VERSION_TEXT,stdout);
			fputs( "Usage: adp [Options] filename... [-A arguments...] \n",stdout);
			fputs( "     : adp [Options] -e \"adp code\" [-A arguments...] \n",stdout);
			fputs( "Options: -c  syntax check only \n",stdout);
			fputs( "       : -cd Change current directory to directory located first source file.\n",stdout);
			fputs( "       : -rc Show recompile code(for debug).\n",stdout);
			fputs( "       : -ss Show session key(for debug).\n",stdout);
			fputs( "       : -t  Show execute time(ms) and clock(ms). \n",stdout);
			fputs( "       : -tc Show execute clock(ms). \n",stdout);
			fputs( "       : -tt Show execute time(ms). \n",stdout);
			fputs( "       : -w  Show warning message.\n",stdout);
			printf( "sizeof(PInteger) = %ld\n",sizeof(PInteger));
			return 1;
		} 
	} else {
		bool appdone = false;
		bool adpargs = false;
		for ( int i = 1; i < argc; i++ ) {	
			if ( argv[i][0] == '-' ) {
				// コマンドライン引数でコードを指定
				if ( strcmp( argv[i], "-e") == 0 && i + 1 < argc ) {
					i++;
					if ( !appdone ) {
						appdone = true;
						string appath = APPLICATIN_GLOBAL;
						adp.compile(appath, true, false);
					}
					adp.compile(argv[i], false);
				}
				if ( strcmp( argv[i], "-c") == 0 ) {
					syntaxcheck = true;
				}
				if ( strcmp( argv[i], "-cd") == 0 ) {
					chdirflg = true;
				}
				if ( strcmp( argv[i], "-rc") == 0 ) {
					compiletrace = true;
				}
				if ( strcmp( argv[i], "-ss") == 0 ) {
					printSessionID = true;
				}
				if ( strcmp( argv[i], "-t") == 0 ) {
					printTime = true;
				}
				if ( strcmp( argv[i], "-tc") == 0 ) {
					printTimeClock = true;
				}
				if ( strcmp( argv[i], "-tt") == 0 ) {
					printTimeTime = true;
				}
				if ( strcmp( argv[i], "-w") == 0 ) {
					dispwarn = true;
				}
				if ( strcmp( argv[i], "-A") == 0 ) {
					// 以降は、adpのArgumentとして扱う
					convertstringvector( argv + i + 1, argvector);
					break;	
				}
			} else {
				bool awp = false;
				if ( (awp = isawp(argv[i])) == true ) {
					header_string = "Content-Type: text/html\r\n";
					#ifdef _WIN32
					_setmode(_fileno(stdout), _O_BINARY);
					#endif
					chdirflg = true;
					awp = true;
				}
				if ( !appdone ) {
					appdone = true;
					string ppath = argv[i];
					string::reverse_iterator ri = find( ppath.rbegin(), ppath.rend(), pseparator);
					if ( ri != ppath.rend() ) {
						first_src_base_path = string( ppath.begin(), ri.base());
					}
					string appath = first_src_base_path + APPLICATIN_GLOBAL;
					adp.compile(appath, true, false);
				}
				adp.compile(argv[i], awp, true);
			}
			
		}
	}
	
	if ( chdirflg ) {
		_chdir( first_src_base_path.c_str() );
	}
	adp.recompile();

	bool ret = adp.prolog();

	print_header();	// 本文がない場合（出力しない場合）ヘッダーが出力されないのでここで出力する（DBに変更を加えてLocationヘッダで飛ばす場合、ここでヘッダーが出力される） 

	if ( sessionwriteflg && session ) {
		// write session to file
		string cvobj;
		string header;
		if ( toBinary( session, cvobj, header) ) {
			basic_ofstream<char> outputFile( sessionpath.c_str(), ios_base::out | ios::binary);
			outputFile << header;
			outputFile << cvobj;
		}
	}

	db_disconnect();

	end_gc();
	
#ifdef _WIN32
    WSACleanup();
#endif

	if ( printTime || printTimeClock ) fprintf(stderr, "Execute time is %5.0fms.(clock)\n", (clock()-c)*1000.0/CLOCKS_PER_SEC); 
	if ( printTime || printTimeTime ) fprintf(stderr, "Execute time is %llds.(time)\n", (PINTEGER)(time(0)-t)); 
	if ( printSessionID && !sessionid.empty() ) fprintf(stderr, ADP_SESSION_ID_STRING"=%s\n", sessionid.c_str());
	
	return ret ? 0 : 1;
}

