#if (sys || nodejs)
import sys.FileSystem;
import sys.io.File;
#end
#if (js && !nodejs)
import js.Browser;
import js.html.Element;
import js.html.SelectElement;
import js.html.TextAreaElement;
#end
import haxe.ds.StringMap;
import code.*;
import database.*;
import graph.*;
import model.*;
import schema.*;
import source.*;
import code.*;
import transform.*;


typedef SParams = {
	var src : String;
	var sType : String; //mocodo
	var dst : String;
	var dType : String; //sqlite, maria/mariadb/mysql, psql/postgresql
	var univ : Bool; //relational model: true to use university format, false for french educational format
}

class DBConcept {
	#if (sys || nodejs)
	public static function main() {
		var p : SParams = loadParams(Sys.args());
		if (p.src == "") {
			printUsage();
		} else {
			switch (p.sType) {
				case "dbc" : generation(p);
				case "sqlite" | "maria" | "mariadb" | "mysql" | "psql" | "postgresql" : dbRetroconception(p);
				default: printUsage();
			}
		}
	}

	static function printUsage() {
		Sys.println("usage: dbconcept -s path/to/source.dbc [-d sqlite[:filename.db]]");
		Sys.println("usage: dbconcept -s path/to/source.dbc [-d maria[:host,db,user,pass]]");
		Sys.println("usage: dbconcept -s path/to/source.dbc [-d psql");
		//~ Sys.println("usage: dbconcept -s path/to/source.dbc [-d <maria|psql>[:host,db,user,pass]]");

		Sys.println("usage: dbconcept -s sqlite:filename.db [-d path/to/destination ]");
		Sys.println("usage: dbconcept -s maria:host,db,user,pass [-d path/to/destination ]");
		//~ Sys.println("usage: dbconcept -s <maria,psql>:host,db,user,pass [-d path/to/destination ]");

		Sys.println("\toption: [--univ] : display format");
}

	static function generation(p : SParams) {
		var diagram : Diagram = null;
		if (!FileSystem.exists(p.src)) {
			Sys.println("error: file '" + p.src + "' not found");
		} else {
			diagram = Mocodo.load(File.getContent(p.src));
		}
		if (diagram != null) {
			var basename : String = p.src.substring(0, p.src.lastIndexOf("."));
			var mld : MLD = DiagramToMLD.transform(diagram);
			DiagramToUML.transform(diagram);
			File.saveContent(basename + ".mld", mld.toString(p.univ));
			File.saveContent(basename + "-mcd.svg", MCDToSVG.generateSVG(diagram).toString());
			File.saveContent(basename + "-mld.svg", MLDToSVG.generateSVG(mld, false).toString());
			File.saveContent(basename + "-mpd.svg", MLDToSVG.generateSVG(mld, true).toString());
			File.saveContent(basename + "-uml-domain.svg", UMLToSVG.generateSVG(diagram, false, true).toString());

			if (p.dType != "") {
				var sql : String = switch (p.dType) {
					case "sqlite" : DBSqlite.generateSQL(mld);
					case "maria" | "mariadb" | "mysql" : DBMariaDB.generateSQL(mld);
					case "psql" | "postgresql" : DBPostgreSQL.generateSQL(mld);
					default : null;
				}
				if (sql != null) {
					var sqlfile : String = basename + "-" + p.dType + ".sql";
					File.saveContent(sqlfile, sql);
					if (p.dst != "") {
						switch (p.dType) {
							case "sqlite" : DBSqlite.createDatabase(p.dst, sqlfile);
							case "maria" | "mariadb" | "mysql" : DBMariaDB.createDatabase(p.dst, sqlfile);
							case "psql" | "postgresql" : DBPostgreSQL.createDatabase(p.dst, sqlfile);
						}
					}
				} else { //p.dType != database -> language
					var files : StringMap<String> = switch (p.dType) { //language
						case "haxe" : code.HaxeCode.generate(diagram);
						case "java" : code.JavaCode.generate(diagram);
						case "python" : code.PythonCode.generate(diagram);
						case "php" : code.PhpCode.generate(diagram);
						default : null;
					}
					if (files != null) {
						if (p.dst != "" && !FileSystem.exists(p.dst)) {
							FileSystem.createDirectory(p.dst);
						}
						for (file in files.keys()) {
							File.saveContent((p.dst == "" ? "" : p.dst + "/") + file, files.get(file));
						}
					}
				}
			}
		}
	}

	static function dbRetroconception(p : SParams) {
		var mld : MLD = null;
		if (p.sType == "sqlite") {
			if (!FileSystem.exists(p.src)) {
				Sys.println("error: file '" + p.src + "' not found");
			} else {
				mld = DBSqlite.analyse(p.src);
			}
		} else if (["maria", "mariadb", "mysql"].indexOf(p.sType) != -1) {
			mld = DBMariaDB.analyse(p.src);
		}
		if (mld != null) {
			var diagram : Diagram = MLDToDiagram.transform(mld);
			DiagramAdapter.arrange(diagram);
			if (p.dst != "" && !FileSystem.exists(p.dst)) {
				FileSystem.createDirectory(p.dst);
			}
			var basename : String = (p.dst == "" ? "" : p.dst + "/") + (p.sType == "sqlite" ? p.src.substring(0, p.src.lastIndexOf(".")) : "rev" + p.sType);
			File.saveContent(basename + ".mld", mld.toString(p.univ));
			File.saveContent(basename + "-mcd.svg", MCDToSVG.generateSVG(diagram).toString());
			File.saveContent(basename + ".dbc", Mocodo.save(diagram));
			File.saveContent(basename + "-mld.svg", MLDToSVG.generateSVG(mld, false).toString());
			File.saveContent(basename + "-mpd.svg", MLDToSVG.generateSVG(mld, true).toString());
			File.saveContent(basename + "-uml-domain.svg", UMLToSVG.generateSVG(diagram, false, true).toString());
		}
	}

	static function loadParams(args : Array<String>) : SParams {
		var params : SParams = { src : "", sType : "", dst : "", dType : "", univ : false };
		var oSrc : Bool = false;
		var oDst : Bool = false;
		for (arg in args) {
			if (arg == "-s") oSrc = true;
			else if (oSrc) {
				oSrc = false;
				if (arg.indexOf(":") != -1) {
					params.sType = arg.substring(0, arg.indexOf(":"));
					params.src = arg.substring(arg.indexOf(":") + 1);
				} else {
					params.sType = "dbc";
					params.src = arg;
				}
			} else if (arg == "-d") oDst = true;
			else if (oDst) {
				oDst = false;
				if (arg.indexOf(":") != -1) {
					params.dType = arg.substring(0, arg.indexOf(":"));
					params.dst = arg.substring(arg.indexOf(":") + 1);
				} else if (["sqlite", "maria", "mariadb", "mysql", "psql", "postgresql"].indexOf(arg) != -1) {
					params.dType = arg;
				} else {
					params.dst = arg;
				}
			} else if (arg == "--univ") params.univ = true;
		}
		return params;
	}
	#end
}
