#include <string.h>
#include "arg.h"
#include "log.h"
#include "dep.h"
#include "db.h"
#include "tmpasm_scconfig.h"

#define VER1 "1"
#define VER2 "0"
#define VER3 "2"

static void help(void)
{
	printf("./configure: configure libmawk.\n");
	printf("\n");
	printf("Usage: ./configure [options]\n");
	printf("\n");
	printf("options are:\n");
	printf(" --prefix=path              change installation prefix from /usr/local to path\n");
	printf(" --debug                    build full debug version (-g -O0, extra asserts)\n");
	printf(" --profile                  build profiling version if available (-pg)\n");
	printf(" --symbols                  include symbols (add -g, but no -O0 or extra asserts)\n");
	printf(" --numeric=int              change the internal numeric type (default is double)\n");
	printf(" --libarchdir=relpath       relative path under prefix for arch-lib-dir (e.g. lib64)\n");
	printf("\n");
}

/* Runs when a custom command line argument is found
 returns true if no furhter argument processing should be done */
int hook_custom_arg(const char *key, const char *value)
{
	if (strcmp(key, "prefix") == 0) {
		put("/local/prefix", value);
		return 1;
	}
	if (strcmp(key, "debug") == 0) {
		put("/local/debug", strue);
		return 1;
	}
	if (strcmp(key, "symbols") == 0) {
		put("/local/symbols", strue);
		return 1;
	}
	if (strcmp(key, "profile") == 0) {
		put("/local/profile", strue);
		return 1;
	}
	if (strcmp(key, "libarchdir") == 0) {
		put("/local/libarchdir", value);
		return 1;
	}
	if (strcmp(key, "numeric") == 0) {
		if ((strcmp(value, "int") == 0) || (strcmp(value, "double") == 0))
			put("/local/numeric", value);
		else {
			fprintf(stderr, "Error: invalid numeric format. Must be int or double\n");
			exit(1);
		}
		return 1;
	}
	if (strcmp(key, "help") == 0) {
		help();
		exit(0);
	}

	return 0;
}


/* Runs before anything else */
int hook_preinit()
{
	return 0;
}

/* Runs after initialization */
int hook_postinit()
{
	db_mkdir("/local");

	/* defaults */
	put("/local/prefix", "/usr/local");
	put("/local/debug", sfalse);
	put("/local/symbols", sfalse);
	put("/local/profile", sfalse);
	put("/local/libarchdir", "lib");

	report("Configuring libmawk.\n");
	logprintf(0, "Configuring libmawk.\n");
	return 0;
}

/* Runs after all arguments are read and parsed */
int hook_postarg()
{
	if (get("/local/numeric") == NULL)
		put("/local/numeric", "double");
	return 0;
}

/* Runs when things should be detected for the host system */
int hook_detect_host()
{
	require("fstools/chmodx", 0, 1);
	require("fstools/cp", 0, 1);
	require("fstools/rm", 0, 1);
	require("fstools/ln", 0, 1);
	require("fstools/mkdir", 0, 1);

	return 0;
}

/* Runs when things should be detected for the target system */
int hook_detect_target()
{
	put("/local/version", VER1 "." VER2 "." VER3);
	put("/local/version/1", VER1);
	put("/local/version/2", VER2);
	put("/local/version/3", VER3);


	/* if there was no custom requirement from the command line, run all requirements in non-fatal mode */
	if (num_custom_reqs < 1) {
		if (istrue(get("/local/debug"))) {
			require("cc/argstd/pedantic", 0, 0);
			require("cc/argstd/ansi", 0, 0);
			require("cc/argstd/Wall", 0, 0);
			append("/target/cc/cflags", " -O0 ");
			append("/target/cc/cflags", get("cc/argstd/ansi"));
			append("/target/cc/cflags", " ");
			append("/target/cc/cflags", get("cc/argstd/pedantic"));
			append("/target/cc/cflags", " ");
			append("/target/cc/cflags", get("cc/argstd/Wall"));
		}
		else
			append("/target/cc/cflags", " -O3 ");
		if (istrue(get("/local/debug")) || istrue(get("/local/symbols")))
			append("/target/cc/cflags", " -g ");
		if (istrue(get("/local/profile"))) {
			require("cc/argstd/pg", 0, 0);
			require("cc/argstd/no-pie", 0, 0);
			append("/target/cc/cflags", " ");
			append("/target/cc/cflags", get("cc/argstd/pg"));
			append("/target/cc/cflags", " ");
			append("/target/cc/cflags", get("cc/argstd/no-pie"));
		}


		require("cc/cc", 0, 1);
		require("cc/fpic", 0, 1);
		require("cc/soname", 0, 0);
		require("cc/rdynamic", 0, 0);
		require("cc/pragma_message",  0, 0);
		require("sys/types/size_t/includes", 0, 0);
		require("libs/fs/realpath/presents", 0, 0);
		require("libs/env/putenv", 0, 1);
		require("libs/io/pipe/presents", 0, 0);
		require("libs/math/cc/log/*", 0, 1);
		require("libs/math/nan/*", 0, 0);
		require("libs/math/isnan/*", 0, 0);
		require("libs/math/nanop/*", 0, 0);

		require("parsgen/bison", 0, 0);
		printf("Numeric format: %s\n", get("/local/numeric"));
	}
	return 0;
}

/* Runs after detection hooks, should generate the output (Makefiles, etc.) */
int hook_generate()
{
	printf("Generating libmawk/Makefile... ");
	fflush(stdout);
	if (tmpasm("../src/libmawk", "Makefile.conf.in", "Makefile.conf") == 0)
		printf("OK\n");
	else
		printf("failed\n");

	printf("Generating libmawk/conf.h... ");
	fflush(stdout);
	if (tmpasm("../src/libmawk", "conf.h.in", "conf.h") == 0)
		printf("OK\n");
	else
		printf("failed\n");

	printf("Generating awklib/Makefile... ");
	fflush(stdout);
	if (tmpasm("../src/awklib", "Makefile.in", "Makefile") == 0)
		printf("OK\n");
	else
		printf("failed\n");

	printf("Generating awklib/regression/Makefile... ");
	fflush(stdout);
	db_mkdir("/local");
	if (tmpasm("../src/awklib/regression", "Makefile.in", "Makefile") == 0)
		printf("OK\n");
	else
		printf("failed\n");

	return 0;
}

/* Runs before everything is uninitialized */
void hook_preuninit()
{
}

/* Runs at the very end, when everything is already uninitialized */
void hook_postuninit()
{
}

