/* vi: set sw=4 ts=4: */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h> 
#include <ctype.h>
#include <sys/types.h>
#include <string.h>

#include "defs.h"
#include "convert.h"
#include "hzinput.h"
#include "pinyin.h"
#include "safestring.h"
#include "cin2tab.h"

static void print_usage(char *progname)
{
	fprintf(stderr, "Usage: %s [-gb|-gbk|-big5|-jis|-ksc|-nocheck|-l <encoding>] [-charonly|-lx|-lx1|-lx2] <input_file> [-o <output_file>]\n", progname);
	fprintf(stderr, "  -l <encoding> can specify encoding(gb/gbk/big5 etc).\n");
	fprintf(stderr, "  -charonly supports cxterm-style file(multiple chars in same line).\n");
	fprintf(stderr, "  -lx supports generation of LianXiang file from cin's phrases.\n");
	fprintf(stderr, "  -lx1 supports generation of LianXiang file from txt phrase file.\n");
	fprintf(stderr, "  -lx2 supports generation of LianXiang file from txt phrase file(first char common).\n");
    
	exit(0);
}

int charonly = 0; /* for big5, put lots of single chars together, like cxterm's tit */
int gen_lx = 0; /* generate lx file */

static void init_input_table(hz_input_table *table)
{

	memset(table, 0, sizeof(*table));
	
	strcpy(table->magic_number, INPUT_MAGIC_NUMBER);

	table->encoding = (SysCoding == SYSCODE_NOCHECK ? CODE_GB : (char)SysCoding);
	table->auto_select = 1;
	table->key_prompt = 0;
	table->key_len = 6;
	table->MaxDupSel = 0;  /* error checking */
	table->wildcard = 0; /* disabled by default */
	table->left_shift_enable = 1; /* enable the left-shift to enter english mode */
	table->prefix_match_enable = 1; /* enable prefix-match */
	table->keyname_bytes = 1;  /* using ASCII by default */
	table->InputType = INPUT_TYPE_TABLE; /* 0x3, default one */
	strcpy(table->ename, "UNKNOWN");
	strcpy(table->cname, "UNKNOWN");
	strcpy(table->selkey, DEFAULT_SELECT_KEYS);  /* default select key */
	strcpy(table->pageprevkey, DEFAULT_PAGEPREV_KEYS);
	strcpy(table->pagenextkey, DEFAULT_PAGENEXT_KEYS);
	strcpy(table->selfirstkey, DEFAULT_SELFIRST_KEYS);
}

int main(int argc, char **argv)
{
	int i,j, len;
	char fname[CCE_PATHNAME_MAX+1],  *fname_out = NULL, fname_lx[CCE_PATHNAME_MAX+1],
     	fname_tab[CCE_PATHNAME_MAX+1], fname_cin[CCE_PATHNAME_MAX+1];
	hz_input_table InpTable;
	FILE *fr;

    if (argc <= 1)
    {
		print_usage(argv[0]); /* will exit */
    }

	if (strncasecmp(argv[1], "-old2new", 8) == 0)
	{
		if (!argv[2]) print_usage(argv[0]);
		return ConvertGBPhraseFormat(0, argv[2]);	
	}
	else if (strncasecmp(argv[1], "-new2old", 8) == 0)
	{
		if (!argv[2]) print_usage(argv[0]);
		return ConvertGBPhraseFormat(1, argv[2]);
	}
	else if (strncasecmp(argv[1], "-gbk", 4) == 0)
    {
        SysCoding = CODE_GBK; argc--; argv++;
    }
    else if (strncasecmp(argv[1], "-gb", 3) == 0)
    {
        SysCoding = CODE_GB; argc--; argv++;
    }
    else if (strncasecmp(argv[1], "-big5", 5) == 0 || strncasecmp(argv[1], "-b5", 3) == 0)
    {
        SysCoding = CODE_BIG5; argc--; argv++;
    }
    else if (strncasecmp(argv[1], "-jis", 4) == 0)
    {
        SysCoding = CODE_EUC; argc--; argv++;
    }
    else if (strncasecmp(argv[1], "-ks", 3) == 0)
    {
        SysCoding = CODE_KSC; argc--; argv++;
    }
    else if (strncasecmp(argv[1], "-nocheck", 8) == 0)
    {
        SysCoding = SYSCODE_NOCHECK; argc--; argv++;
    }
	else if (strncmp(argv[1], "-l", 2) == 0) /* for XCIN's cin2tab compatibility */
	{
		if (argv[2] && identify_encoding(argv[2]) > 0)
			SysCoding = identify_encoding(argv[2]);
		argc -= 2; argv += 2;
	}

	if (strncasecmp(argv[1], "-charonly", 9) == 0) 
	{
		charonly = 1; argc--; argv++;
	}
#ifdef SUPPORT_ASSOCIATE
	else if (strncasecmp(argv[1], "-lx1", 4) == 0)
	{
		gen_lx = 1;  argc--; argv++;
	}
	else if (strncasecmp(argv[1], "-lx2", 4) == 0)
	{
	    gen_lx = 2;  argc--; argv++;
	}
	else if (strncasecmp(argv[1], "-lx", 3) == 0)
	{
		gen_lx = 3; argc--; argv++;
	}
	
	if (SysCoding == SYSCODE_NOCHECK && gen_lx > 0) SysCoding = CODE_GB; /* we do need SysCoding for lx */
#endif

	if (argc <= 1) 
	{
		fprintf(stderr, "Enter table file name [.cin] : ");
		fgets(fname, CCE_PATHNAME_MAX+1-4+1, stdin);
		strtok(fname, "\n");  /* Drop the possible final LF character */

	}
	else 
	{
		safe_strncpy(fname, argv[1], CCE_PATHNAME_MAX+1-4);
		i = strlen(fname);
		if ( i > 4 && strncmp(fname + i - 4, ".cin", 4) == 0 )  
			fname[i-4] = '\0';

		argc--; argv++;
		if (argv[1] && strncasecmp(argv[1], "-o", 2) == 0)
		{
			argc--; argv++;
			fname_out = argv[1];		
		}
	}

	len = strlen(fname);
	i = len - 1;
	CurCINPath[0] = '\0'; /* null string */
	while(i >= 0 && fname[i] != '/') i--;  /* i pointing to the '/' or -1 */
	for(j = 0; j <= i; j++)
		CurCINPath[j] = fname[j];
	CurCINPath[j] = '\0';

	strcpy(fname_cin,fname);   /* in original directory */
	strcat(fname_cin,".cin");

	if ((fr=fopen(fname_cin,"r"))==NULL ) 
	{
		if ((fr = fopen(fname, "r")) == NULL)
			print_error("Cannot open %s \n", fname_cin);
	}

    for(j = i+1; j <= len; j++)   /* delete all the path information, just keep filename */
		fname[j-i-1] = fname[j];
	
	strcpy(fname_tab,fname);
	strcat(fname_tab,".tab");
	strcpy(fname_lx,fname /* _tab */);
	strcat(fname_lx,".lx");

#ifdef SUPPORT_ASSOCIATE
	if (gen_lx == 1 || gen_lx == 2)
	{
		i = strlen(fname);
		if (i > 4 && strncmp(fname + i - 4, ".asc", 4) == 0 ) 
		{
			fname[i-4] = '\0';
			strcpy(fname_lx, fname);
			strcat(fname_lx, ".lx"); /* *.asc -> *.lx */
		}
		return GenerateAssociateFile(fr, gen_lx, fname_out && *fname_out ? fname_out : fname_lx);
	}
#endif

	init_input_table(&InpTable);

	cmd_arg(fr,LineBuf,&cmd, &arg); /* read 1st line */
	if (!strncasecmp(cmd, MSMB_DESC_STR, strlen(MSMB_DESC_STR)))
	{
		read_msmb_format(fr, &InpTable);
		cmd = "";  /* make it empty, otherwise %keyname will be there */
	}
	else
	{   /* assuming it's CIN format */
		read_cin_options(fr, &InpTable);
	
		read_cin_keyname(fr, &InpTable);
	}

#ifdef DEBUG
	fprintf(stderr, "Generating binary *.tab file for input method %s...\n",fname_cin);
#endif

	switch(InpTable.InputType)
	{
	case INPUT_TYPE_PINYIN:
		return ConvertPinyinCIN(fr, &InpTable, fname_tab );
	case INPUT_TYPE_ZHUYIN:
		return ConvertZhuyinCIN(fr, &InpTable, fname_tab );
	case INPUT_TYPE_INTCODE:
	case INPUT_TYPE_TABLE:
		return ConvertTableCIN(fr, &InpTable, fname_cin, 
				fname_out && *fname_out ? fname_out : fname_tab, fname_lx);
	default:
		return -1;
	}

	return 0;	
}
