/****************************************************************************
 * KONOHA COPYRIGHT, LICENSE NOTICE, AND DISCRIMER
 *
 * Copyright (c) 2005-2008, Kimio Kuramitsu <kimio at ynu.ac.jp>
 *           (c) 2008-      Konoha Software Foundation
 * All rights reserved.
 *
 * You may choose one of the following two licenses when you use konoha.
 * See www.konohaware.org/license.html for further information.
 *
 * (1) GNU General Public License 2.0      (with    KONOHA_UNDER_GPL2)
 * (2) Konoha Software Foundation License 1.0
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 COPYRIGHT OWNER
 * OR CONTRIBUTORS 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.
 *
 ****************************************************************************/

/* ************************************************************************ */

#include"commons.h"

/* ************************************************************************ */

#ifdef __cplusplus
extern "C" {
#endif

/* ------------------------------------------------------------------------ */
/* [declc] */

void knh_StmtIMPORT_decl(Ctx *ctx, Stmt *stmt, Compiler *cpr, NameSpace *ns, int level)
{
	String *fname = (String*)DP(StmtIMPORT_file(stmt))->data;
	if(IS_String(fname)) {
		char bufp[FILENAME_BUFSIZ], buff[FILENAME_BUFSIZ];
		String *cfname = knh_tfileid_name(SP(stmt)->fileid);
		if(knh_String_endsWith(cfname, STEXT(".k"))) {
			knh_format_parentpath(bufp, sizeof(bufp), knh_String_tobytes(cfname), 1);
		}
		else {
			bufp[0]=0;
		}

		knh_format_catpath(buff, sizeof(buff), B(bufp), knh_String_tobytes(fname));
		knh_fileid_t fileid = knh_tName_getFileId(ctx, B(buff));
		if(knh_NameSpace_isLoaded(ctx, ns, fileid)) {
			DEBUG3("already imported %s", buff);
		}
		else {
			DEBUG3("import %s", buff);
			knh_NameSpace_loaded(ctx, ns, fileid);
			knh_format_ospath(bufp, sizeof(bufp), B(buff));

			FILE *fp = knh_fopen(bufp, "r");
			if(fp == NULL) {
				knh_Compiler_perror(ctx, cpr, KMSG_USCRIPT, buff);
				knh_Stmt_done(ctx, stmt);
				return;
			}
			else {
				InputStream *in = new_InputStream__FILE(ctx, fp);
				DP(in)->fileid = fileid;
				knh_InputStream_setEncoding(ctx, in, knh_systemEncoding);
				knh_konohac_eval(ctx, DP(ns)->nsname, in);
			}

		}
	}
	knh_Stmt_done(ctx, stmt);
}

/* ------------------------------------------------------------------------ */

void knh_StmtUIMPORT_decl(Ctx *ctx, Stmt *stmt, Compiler *cpr, NameSpace *ns, int level)
{
	Token *tk = DP(stmt)->tokens[0];
	knh_bytes_t name = knh_Token_tobytes(tk);
	knh_index_t loc = knh_bytes_rindex(name, '.');
	if(loc != -1) {
		if(knh_System_using(ctx, knh_bytes_first(name, loc))) {
			knh_class_t newcid = knh_NameSpace_getClass(ctx, knh_rootNameSpace, name);
			if(newcid == CLASS_unknown) {
				knh_Token_perror(ctx, tk, KMSG_UCLASSN);
				knh_Stmt_done(ctx, stmt);
				return;
			}
			knh_class_t oldcid = knh_NameSpace_getClass(ctx, ns, knh_bytes_last(name, loc+1));
			if(oldcid != CLASS_unknown && newcid != oldcid) {
				KNH_WARNING(ctx, "ovrriding.. %s => %s", CLASSN(oldcid), CLASSN(newcid));
			}
			knh_NameSpace_setLocalName(ctx, ns, newcid);
			knh_Stmt_done(ctx, stmt);
			return;
		}
	}else {
		if(knh_System_using(ctx, name)) {
			if(knh_Token_isTailWildCard(tk)) {
				knh_NameSpace_import(ctx, ns, name);
			}
			knh_Stmt_done(ctx, stmt);
			return;
		}
	}
	knh_Token_perror(ctx, tk, KMSG_UPACKAGE);
}

/* ------------------------------------------------------------------------ */

void knh_StmtUALIAS_decl(Ctx *ctx, Stmt *stmt, Compiler *cpr, NameSpace *ns, int level)
{
	DBG2_DUMP(ctx, stmt, KNH_NULL, "decl");
	TODO();
	knh_Stmt_done(ctx, stmt);
}

/* ------------------------------------------------------------------------ */

void knh_StmtUVOCAB_decl(Ctx *ctx, Stmt *stmt, Compiler *cpr, NameSpace *ns, int level)
{
	DBG2_DUMP(ctx, stmt, KNH_NULL, "decl");
	TODO();
//	//DEBUG_STMT(ctx, stmt);
//	//Compiler *mc = (Compiler*)v;
//	/* ['CLASSTN', 'CURN'] */
//
//	Compiler *b = (Compiler*)v;
//	Token *tkc = (Token*)stmt->terms[0];
//	Token *tku = (Token*)stmt->terms[1];
//	KNH_ASSERT(IS_Token(tkc)); KNH_ASSERT(IS_Token(tku));
//	NameSpace *ns = knh_Compiler_getNameSpace(ctx, b);
//
//	knh_class_t cid = knh_tclass_classURN(ctx, CLASS_String, knh_Token_tobytes(tku));
//	if(cid == CLASS_String) {
//		MC_EPRINT(ctx, tkc, MC_ERRATA, "undefined '%s': %s => %s",
//			knh_Token_tochar(tku), knh_Token_tochar(tkc), CLASSN(cid));
//		return;
//	}
//
//	knh_class_t oldcid = knh_NameSpace_getClass(ctx, ns, knh_Token_tobytes(tkc));
//	if(oldcid != CLASS_unknown && cid != oldcid) {
//		MC_EPRINT(ctx, tkc, MC_INFO, "renaming class: %s => %s", CLASSN(oldcid), CLASSN(cid));
//	}
//
//	KNH_ASSERT(IS_String(tkc->data));
//	knh_NameSpace_setLocalName(ctx, ns, tkc->data, cid);
//
	knh_Stmt_done(ctx, stmt);
}

/* ------------------------------------------------------------------------ */

void knh_StmtUENUM_decl(Ctx *ctx, Stmt *stmt, Compiler *cpr, NameSpace *ns, int level)
{
	DBG2_DUMP(ctx, stmt, KNH_NULL, "decl");
	TODO();
//	//DEBUG_STMT(ctx, stmt);
//	//Compiler *mc = (Compiler*)v;
//	/* ['CLASSTN', 'CURN'] */
//
//	Compiler *b = (Compiler*)v;
//	Token *tkc = (Token*)stmt->terms[0];
//	Token *tku = (Token*)stmt->terms[1];
//	KNH_ASSERT(IS_Token(tkc)); KNH_ASSERT(IS_Token(tku));
//	NameSpace *ns = knh_Compiler_getNameSpace(ctx, b);
//
//	knh_class_t cid = knh_tclass_classURN(ctx, CLASS_Int, knh_Token_tobytes(tku));
//	if(cid == CLASS_Int) {
//		MC_EPRINT(ctx, tkc, MC_ERRATA, "undefined '%s': %s => %s",
//			knh_Token_tochar(tku), knh_Token_tochar(tkc), CLASSN(cid));
//		return;
//	}
//
//	knh_class_t oldcid = knh_NameSpace_getClass(ctx, ns, knh_Token_tobytes(tkc));
//	if(oldcid != CLASS_unknown && cid != oldcid) {
//		MC_EPRINT(ctx, tkc, MC_INFO, "renaming class: %s => %s", CLASSN(oldcid), CLASSN(cid));
//	}
//
//	KNH_ASSERT(IS_String(tkc->data));
//	knh_NameSpace_setLocalName(ctx, ns, tkc->data, cid);

	knh_Stmt_done(ctx, stmt);
}

/* ------------------------------------------------------------------------ */

void knh_StmtUUNIT_decl(Ctx *ctx, Stmt *stmt, Compiler *cpr, NameSpace *ns, int level)
{
	DBG2_DUMP(ctx, stmt, KNH_NULL, "decl");
	TODO();
//	//DEBUG_STMT(ctx, stmt);
//	/* ['CLASSTN', 'CURN'] */
//	Compiler *b = (Compiler*)v;
//	Token *tkc = (Token*)stmt->terms[0];
//	Token *tku = (Token*)stmt->terms[1];
//	KNH_ASSERT(IS_Token(tkc)); KNH_ASSERT(IS_Token(tku));
//	NameSpace *ns = knh_Compiler_getNameSpace(ctx, b);
//
//	knh_class_t cid = knh_tclass_classURN(ctx, CLASS_Float, knh_Token_tobytes(tku));
//	if(cid == CLASS_Float) {
//		MC_EPRINT(ctx, tkc, MC_ERRATA, "undefined '%s': %s => %s",
//			knh_Token_tochar(tku), knh_Token_tochar(tkc), CLASSN(cid));
//		return;
//	}
//
//	knh_class_t oldcid = knh_NameSpace_getClass(ctx, ns, knh_Token_tobytes(tkc));
//	if(oldcid != CLASS_unknown && cid != oldcid) {
//		MC_EPRINT(ctx, tkc, MC_INFO, "renaming class: %s => %s", CLASSN(oldcid), CLASSN(cid));
//	}
//
//	KNH_ASSERT(IS_String(tkc->data));
//	knh_NameSpace_setLocalName(ctx, ns, tkc->data, cid);

	knh_Stmt_done(ctx, stmt);
}

/* ------------------------------------------------------------------------ */

void knh_StmtUFUNC_decl(Ctx *ctx, Stmt *stmt, Compiler *cpr, NameSpace *ns, int level)
{
	Token *tk = DP(stmt)->tokens[0];
	knh_bytes_t name = knh_Token_tobytes(tk);
	if(SP(tk)->tt == TT_CMETHODN) {
		knh_index_t loc = knh_bytes_rindex(name, '.');
		knh_class_t cid = knh_NameSpace_getClass(ctx, ns, knh_bytes_first(name, loc));
		if(cid == CLASS_unknown) {
			knh_Token_perror(ctx, tk, KMSG_UCLASSN);
			knh_Stmt_done(ctx, stmt);
			return;
		}
		knh_methodn_t mn = knh_tName_getMethodn(ctx, knh_bytes_last(name, loc+1), METHODN_NONAME);
		if(mn == METHODN_NONAME) {
			knh_Token_perror(ctx, tk, KMSG_UMETHODN);
			knh_Stmt_done(ctx, stmt);
			return;
		}
		knh_NameSpace_setFuncClass(ctx, ns, mn, cid);
	}
	else {
		knh_class_t cid = knh_NameSpace_getClass(ctx, ns, name);
		if(cid == CLASS_unknown) {
			knh_Token_perror(ctx, tk, KMSG_UCLASSN);
			knh_Stmt_done(ctx, stmt);
			return;
		}
		else {
			DEBUG_ASSERT_cid(cid);
			Array *a = DP(knh_tClass[cid].cstruct)->methods;
			int i;
			for(i = 0; i < knh_Array_size(a); i++) {
				Method *mtd = (Method*)knh_Array_n(a, i);
				KNH_ASSERT(IS_Method(mtd));
				if(!knh_Method_isClassFunc(mtd)) continue;
				knh_NameSpace_setFuncClass(ctx, ns, DP(mtd)->mn, cid);
				if(knh_Context_isVerbose(ctx)) {
					char bufcm[CLASSNAME_BUFSIZ];
					knh_format_cmethodn(bufcm, sizeof(bufcm), cid, DP(mtd)->mn);
					KNH_NOTICE(ctx, "using %s", bufcm);
				}
			}
		}
	}
	knh_Stmt_done(ctx, stmt);
}

/* ------------------------------------------------------------------------ */

void knh_StmtUMAPMAP_decl(Ctx *ctx, Stmt *stmt, Compiler *cpr, NameSpace *ns, int level)
{
	DBG2_DUMP(ctx, stmt, KNH_NULL, "decl");
	TODO();
	knh_Stmt_done(ctx, stmt);
}

/* ------------------------------------------------------------------------ */

void knh_StmtUALIAS(Ctx *ctx, Stmt *stmt, Compiler *cpr, NameSpace *ns, int level)
{
	DBG2_DUMP(ctx, stmt, KNH_NULL, "decl");
	TODO();
	knh_Stmt_done(ctx, stmt);
}

///* ------------------------------------------------------------------------ */
//
//void knh_stmtvisit_declc__weave(Ctx *ctx, Stmt *stmt, Compiler *cpr, NameSpace *ns, int level)
//{
//	//DEBUG_STMT(ctx, stmt);
//	//Compiler *mc = (Compiler*)v;
//	/* ['weave', 'ANY', 'METHODFN'] */
//	fprintf(stdout, "weaving %s into %s..\n", knh_Token_tochar((Token*)stmt->terms[1]), knh_Token_tochar((Token*)stmt->terms[2]));
//	Method *mtd = knh_Class_getMethod(ctx, CLASS_Amazon, METHODN_placeOrder);
//	if(IS_Method(mtd)) {
//		String *aspect = ((Token*)stmt->terms[1])->data;
//		if(IS_NULL(aspect)) {
//			knh_weave(ctx, NULL, mtd);
//		}
//		else if(knh_String_equals(aspect, STEXT("null"))) {
//			knh_weave(ctx, NULL, mtd);
//		}
//		else if(knh_String_equals(aspect, STEXT("RBAC"))) {
//			knh_weave(ctx, knh_security_RBAC, mtd);
//		}
//		else if(knh_String_equals(aspect, STEXT("Audit"))) {
//			knh_weave(ctx, knh_security_Audit, mtd);
//		}
//		else {
//			KNH_THROWf(ctx, "NoSuchAspect!!: %s", knh_String_tochar(aspect));
//		}
//	}
//	else{
//		DEBUG("what?");
//	}
//	knh_Stmt_done(ctx, stmt);
//}

/* ------------------------------------------------------------------------ */

#ifdef __cplusplus
}
#endif
