// nv - stripped-down version of converter for database I/O only 
#include "converter.h"
#include "tools_base.h"
#include "db_tools.h"
#include "xr_file_system.h"
#include "xr_log.h"
#include <stdio.h>

using namespace xray_re;

void usage()
{
	printf("Shadow of Chernobyl database patcher/unpacker/packer 1.0 (%s)\n", BUILD_DATE);
	printf("   derived by NatVac from bardak's X-Ray game asset converter's database i/o\n\n");
	printf("Usage: socpup <common-options> <format-specific-options> <input-object>\n\n");
	printf("Common options (optional):\n");
	printf(" -ro		perform all the steps but do not write anything on disk\n");
	printf(" -verbose	list all files and directories processed\n");
	printf(" -out <PATH>	output file name (DB pack), default: dir as extension\n");
	printf(" -dir <PATH>	output folder name (DB unpack), default: extension\n");
	printf(" -extract[x] <PATH>	specific file or folder name (DB unpack)\n\n");

	printf("DB options:\n");
	printf(" -unpack	unpack game archive (expects file name)\n");
	printf(" -pack		pack game archive (expects folder name)\n");
	printf(" -patchfile	patch extracted game archive (expects file name)\n");

	printf(" -2947ru	assume CIS release version format\n");
	printf(" -2947ww	assume world-wide release version format (default)\n");
	printf(" -xdb		assume .xdb archive format\n");
	printf(" -11xx or -2215 or -2945	assume 1114/1154, 2215, 2945/2939 (unpack only)\n");
	// printf(" -2215		assume 2215 archive format (full unpack only)\n");
	// printf(" -2945		assume 2945/2939 archive format (full unpack only)\n");
}

int main(int argc, char* argv[])
{
	static const cl_parser::option_desc options[] = {
		{"-unpack",	cl_parser::OT_BOOL},
		{"-pack",	cl_parser::OT_BOOL},
		{"-11xx",	cl_parser::OT_BOOL},
		{"-2215",	cl_parser::OT_BOOL},
		{"-2945",	cl_parser::OT_BOOL},
		{"-2947ru",	cl_parser::OT_BOOL},
		{"-2947ww",	cl_parser::OT_BOOL},
		{"-xdb",	cl_parser::OT_BOOL},

		{"-extract",	cl_parser::OT_STRING},
		{"-extractx",	cl_parser::OT_STRING},
		{"-patchfile",	cl_parser::OT_STRING},

		{"-out",	cl_parser::OT_STRING},
		{"-dir",	cl_parser::OT_STRING},

		{"-ro",		cl_parser::OT_BOOL},
		{"-verbose",	cl_parser::OT_BOOL} //,
	};

	int result = 0;
	cl_parser cl;
	if (!cl.parse(argc, argv, xr_dim(options), options)) {
		usage();
		return RESULT_FAILURE;
	}

	unsigned format = tools_base::TOOLS_AUTO;
	if (cl.exist("-unpack"))
		format |= tools_base::TOOLS_DB;
	if (cl.exist("-pack"))
		format |= tools_base::TOOLS_FOLDER;
	if (cl.exist("-patchfile"))
		format |= tools_base::TOOLS_PATCHER;
	if (format == tools_base::TOOLS_AUTO) {
		std::string extension;
		size_t num_params = cl.num_params();
		for (size_t i = 0; i != num_params; ++i) {
			if (xr_file_system::folder_exist(cl.param(i))) {
				format |= tools_base::TOOLS_FOLDER;
			} else {
				xr_file_system::split_path(cl.param(i), 0, 0, &extension);
				if (db_tools::is_known(extension))
					format |= tools_base::TOOLS_DB;
			}
		}
		if (format == tools_base::TOOLS_AUTO) {
			if (num_params)
				msg(" Can't auto-detect the source format.");
			else
				usage();
			return RESULT_FAILURE;
		}
	}
	if ((format & (format - 1)) != 0) {
		msg(" Conflicting source formats supplied.");
		return RESULT_FAILURE;
	}

 	const char* fs_spec = 0;
/*
	if (format == tools_base::TOOLS_LEVEL ||
			format == tools_base::TOOLS_DDS ||
			format == tools_base::TOOLS_FANCY) {
		if (!cl.get_string("-fs", fs_spec))
			fs_spec = DEFAULT_FS_SPEC;
		if (!xr_file_system::file_exist(fs_spec)) {
			msg("can't find %s", fs_spec);
			return RESULT_FAILURE;
		}
	}
 */
	unsigned fs_flags = 0;
	if (cl.get_bool("-ro")) {
		fs_flags |= xr_file_system::FSF_READ_ONLY;
		msg("  Working in read-only mode...");
	}
	xr_file_system& fs = xr_file_system::instance();
	if (!fs.initialize(fs_spec, fs_flags)) {
		msg(" Can't initialize the file system.");
		return RESULT_FAILURE;
	}
	xr_log::instance().init("socpup", 0); //("converter", 0);

	tools_base* tools = 0;
	switch (format) {
	case tools_base::TOOLS_DB:
		tools = new db_unpacker;
		break;
	case tools_base::TOOLS_FOLDER:
		tools = new db_packer;
		break;
	case tools_base::TOOLS_PATCHER:
		tools = new file_patcher;
		break;
	}
	if (tools == 0) {
		msg(" Unable to proceed - no matching option found.");
		return RESULT_FAILURE;
	}
	result = tools->process(cl);
	delete tools;
	return result;
}

void tools_base::check_path(const char* path, bool& status) const
{
	xr_file_system& fs = xr_file_system::instance();
	if (!fs.folder_exist(path, "")) {
		msg(" Path %s does not exist", path);
		status = false;
	}
}
