#include <applicat.h>
#include <automask.h>
#include <defmask.h>
#include <extcdecl.h>
#include <modaut.h>
#include <odbcrset.h>
#include <prefix.h>
#include <relation.h>
#include <sheet.h>
#include <tree.h>
#include <treectrl.h>
#include <utility.h>
#include <xml.h>

///////////////////////////////////////////////////////////
// TSQL_exec_recordset_app
///////////////////////////////////////////////////////////

class TSQL_exec_recordset_app : public TSkeleton_application
{
protected:
	const TString & load_query(const char * query);
	bool set_vars(const char* values, TRecordset& recset) const;
	bool ask_vars(const char* maskname, TRecordset& recset) const;
	TRecordset* new_recordset(const char * query, const char * values);
	const char * get_output_filename(const char * output, const char * query);
	void save_as(TRecordsetExportFormat fmt, const char* ext = NULL);

public:
  virtual bool create();
  virtual void main_loop();
  virtual bool destroy() { return true;	}
};

// Carica l'intera query
const TString & TSQL_exec_recordset_app::load_query(const char * query)
{
	TFilename path(query);
	TString sqlstr;

	path.ext("qry");
	if (path.full())
	{
		bool ok = path.exist();

		if (!ok)
		{
			if (!path.is_absolute_path())
			{
				path = firm2dir(-1);
				path.add("custom");
				if (!path.exist())
					xvt_fsys_mkdir(path);
				path.add(query);
			}
			path.ext("qry");
			ok = path.exist();
		}
		if (ok)
		{
			TXmlItem xml;
			ok = xml.Load(path);
			if (ok)
			{
				path = path.name(); path.ext("");

				const TXmlItem* desc = xml.FindFirst("description");
				if (desc != nullptr)
				{
					TString str; desc->GetEnclosedText(str);
					if (str.blank())
						str = path.name_only();
					main_app().set_title(str);
				}
				const TXmlItem* sql = xml.FindFirst("sql");
				if (sql != nullptr)
					sql->GetEnclosedText(sqlstr);
			}
		}
	}
	return get_tmp_string() = sqlstr;
}

bool TSQL_exec_recordset_app::set_vars(const char* values, TRecordset& recset) const
{
	if (recset.variables().items() == 0)
		return true;

	TToken_string vals(values, ',');
	TString_array vars = recset.variables();

	// Rendi visibili tutte le variabili utente al report
	FOR_EACH_STR_TOKEN(vals, s)
	{
		TToken_string line(s, '='); 
		TString name = line.get();
		TString val = line.get();
		TDate d(val);

		if (d.ok())
		{
			val.cut(0);
			val << d.date2ansi();
		}
		if (name[0] != '#')
				name.insert("#");

		const int pos = vars.find(name);
			
		if (pos >= 0)
		{
			vars.remove(pos, true);
			recset.set_var(name, val, true);
		}
	}
	return vars.items() == 0;
}

bool TSQL_exec_recordset_app::ask_vars(const char* maskname, TRecordset& recset) const
{
	if (recset.variables().items() == 0)
		return true;

	TFilename fname = maskname; fname.ext("msk");
	KEY key = K_QUIT;
	if (!fname.custom_path())
		return recset.ask_variables(true);

	TMask m(maskname);
	TString title; m.get_caption(title);
	if (title.full())
		main_app().set_title(title);

	TVariant var;
	for (int i = m.fields() - 1; i >= 0; i--)
	{
		TMask_field& f = m.fld(i);
		const TFieldref* ref = f.field();
		if (ref != NULL)
		{
			TString name = ref->name();
			if (name[0] != '#')
				name.insert("#");
			const TVariant& var = recset.get_var(name);
			if (!var.is_null())
				f.set(var.as_string());
		}
	}
	key = m.run();
	const bool ok = key != K_QUIT && key != K_ESC;
	if (ok)
	{
		// Rendi visibili tutte le variabili utente al report
		for (int i = m.fields() - 1; i >= 0; i--)
		{
			TMask_field& f = m.fld(i);
			const TFieldref* ref = f.field();
			if (ref != NULL)
			{
				switch (f.class_id())
				{
				case CLASS_CURRENCY_FIELD:
				case CLASS_REAL_FIELD:
					var = real(f.get());
					break;
				case CLASS_DATE_FIELD:
					var = TDate(f.get());
					break;
				default:
					var = f.get();
					break;
				}
				TString name = ref->name();
				if (name[0] != '#')
					name.insert("#");
				recset.set_var(name, var, true);
			}
		}
	}
	return ok;
}

TRecordset* TSQL_exec_recordset_app::new_recordset(const char * query, const char * values)
{
	const TString& sql = load_query(query);
	TRecordset* rex = create_recordset(sql);

	if (rex != nullptr)
	{
		if (values && *values)
		{
			if (!set_vars(values, *rex))
				safe_delete(rex);
		}
		else
		{
		if (!ask_vars(query, *rex))
			safe_delete(rex);
		}
	}
	return rex;
}

const char * TSQL_exec_recordset_app::get_output_filename(const char * output, const char * query)
{
	TFilename outfname(output);
	TFilename fname;

	if (outfname.blank())
		outfname.tempdir();
	if (!is_dir(outfname))
	{
		fname = outfname.name_only();
		outfname = outfname.path();
	}
	if (!dexist(outfname))
		if (!make_dir(outfname))
		{
			error_box(FR("Non posso creare %s uso il direttorio temporaneo"), (const char *)outfname);
			outfname = outfname.tempdir();
		}
	if (fname.blank())
	{
		TString t(20);

		fname = query;
		fname.ext("");
		_strtime_s(t.get_buffer(), t.size());
		t.strip(":");
		fname << '_' << today.date2ansi() << '_' << t;
	}
	outfname.add(fname);
	return get_tmp_string() = outfname;
}
bool TSQL_exec_recordset_app::create()
{
  if (!has_module(RSAUT))
    return error_box(TR("Modulo non autorizzato"));
	xvt_vobj_show(TASK_WIN);
  xvt_sys_sleep(500);  // Lasciamo il tempo di leggere il titolo

  return TSkeleton_application::create();
}

void TSQL_exec_recordset_app::main_loop()
{
  TFilename query = argv(2); // Carico la query da riga di comando
	TFilename output = get_output_filename(argv(3), query);
	TRecordsetExportFormat fmt = fmt_unknown;
	const char f = argv(4)[0];

	query.ext("qry");
	switch (toupper(f))
	{
	case 'H':
		fmt = fmt_html;
		output.ext("html");
		break;
	case 'T':
		fmt = fmt_text;
		output.ext("txt");
		break;
	case 'E':
	case 'X':
		fmt = fmt_csv;
		output.ext("csv");
		break;
	case 'C':
		fmt = fmt_campo;
		output.ext("txt");
		break;
	case 'D':
		fmt = fmt_dbf;
		output.ext("dbf");
		break;
	default:
		fmt = fmt_html;
		break;
	}

	TString values;

	if (argc() > 5)
		values = argv(5);

	TRecordset * rex = new_recordset(query, values);

	if (values.full() || rex->variables().items() == 0)
	{
		xvt_vobj_hide(TASK_WIN);
		batch();
	}
	if (rex)
		rex->save_as(output, fmt, 0x4);
	safe_delete(rex);
	batch(false);
}

int ba8800(int argc, char* argv[])
{     
  TSQL_exec_recordset_app app;

  app.run(argc, argv, TR("Query Executor"));
  return 0;
}