/**********************************************************************
    cbedic.cpp

    This file is part of the CBE Dictionary package

    Copyright (c) 2001 Antoby - antoby@mail.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Id: cbedic.cpp,v 1.9 2001/03/26 13:50:08 bbi Exp $

**********************************************************************/


#include <iostream.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include "defaults.h"
#include "translator.h"
#include "registry.h"

#include "messages.h"

int interactive_loop(Translator *, int);
int check_word(const char *);
void cbeconfig();

/////////////////////////////////////////////////////////////////////////////

    Registry *reg;

    bool separate_meanings      = false,
         latin_input            = false,
         latin_output           = false,
         html_output            = false,
         exact_match            = false,
         start_interactive      = false;

    char en_bg_filename[FILENAME_LENGTH];
    char bg_en_filename[FILENAME_LENGTH];

/////////////////////////////////////////////////////////////////////////////


int main(int argc, char **argv)
{
    char c;
    extern int optind;

    char *translation = NULL;

    // Read data from config file
    reg = new Registry(getenv(ENV_HOME), REGISTRY_FILE, REGISTRY_FILE_SUFFIX);

    separate_meanings = reg->getBool(OPTION_SEPARATE_MEANINGS, DEFAULT_SEPARATE_MEANINGS);
    latin_input = reg->getBool(OPTION_LATIN_INPUT, DEFAULT_LATIN_INPUT);
    latin_output = reg->getBool(OPTION_LATIN_OUTPUT, DEFAULT_LATIN_OUTPUT);
    html_output = reg->getBool(OPTION_HTML_OUTPUT, DEFAULT_HTML_OUTPUT);
    exact_match = reg->getBool(OPTION_EXACT_MATCH, DEFAULT_EXACT_MATCH);

    strncpy(en_bg_filename, reg->getString(OPTION_ENG_BUL_DAT, ENG_BUL_DAT), FILENAME_LENGTH-1);
    strncpy(bg_en_filename, reg->getString(OPTION_BUL_ENG_DAT, BUL_ENG_DAT), FILENAME_LENGTH-1);
    en_bg_filename[FILENAME_LENGTH-1] = '\0';
    bg_en_filename[FILENAME_LENGTH-1] = '\0';

    cout << PACKAGE << " - Console Bulgarian/English dictionary v" << VERSION << " by Antoby" << endl;

    while((c = getopt(argc, argv, "cwslueih")) != EOF){
	switch(c){
	    case 'w':
		html_output = true;
		break;
	    case 's':
		separate_meanings = true;
		break;
	    case 'l':
		latin_output = true;
		break;
	    case 'u':
		latin_input = true;
		break;
	    case 'e':
		exact_match = true;
		break;
	    case 'i':
		start_interactive = !start_interactive;
		break;
	    case 'c':
		cbeconfig();
		delete reg;
		exit(0);
	    case 'h':
	    default:
		cout << "Usage: " << argv[0] << " [-c | -wslueih]" << endl;
		cout << "\t-c\tconfigure cbedic (" << REGISTRY_FILE << ")" << endl;
		cout << "\t-w\tweb output (HTML)" << endl;
		cout << "\t-s\tseparate menings" << endl;
		cout << "\t-l\tlatin output" << endl;
		cout << "\t-u\tlatin input" << endl;
		cout << "\t-e\tmatch the exact word" << endl;
		cout << "\t-i\tswitch interactive mode" << endl;
		cout << "\t-h\tthis help screen" << endl << endl;
		exit(1);
	};
    };

    delete reg;
    cout << endl;

    Translator dict(MAX_WORD_LEN_2, MAX_WORDS_ALLOWED_2);

    // load EN->BG dictionary
    if(!dict.createDictionary(en_bg_filename, dict.ENG_BUL)){
	cout << "Can not find English->Bulgarian dictionary '" << en_bg_filename << "'" << endl;
	exit(1);
    }

    // load BG->EN dictionary
    if(!dict.createDictionary(bg_en_filename, dict.BUL_ENG)){
	cout << "Can not find Bulgarian->English dictionary '" << bg_en_filename << "'" << endl;
	exit(1);
    }

    dict.latinInput = latin_input;
    dict.latinOutput = latin_output;
    dict.separateMeanings = separate_meanings;
    dict.boldDecoration = true;
    dict.htmlOutput = html_output;

    if(start_interactive){
	interactive_loop(&dict, exact_match);
    } else {
	if(optind < argc){
	    if(!dict.findWord(argv[optind], &translation)){
	        cout << "word not found." << endl;
	        if(exact_match)
		    return 1;
	    }

	    if (translation[0] != '\0') {
	        cout << translation;
	    }
        } else {
	    cout << "Please specify a word to translate or type '" << argv[0] << " -h' for help" << endl;
	    return 1;
        }
    }
    cout << endl;
    return 0;
}

/////////////////////////////////////////////////////////////////////////////

int interactive_loop(Translator *dict, int exact_match)
{
	char word[MAX_WORD_LEN_2];
	char *translation = NULL;
	const char *msg_onoff[] = { "off", "on" };

	cout << "Entered interactive mode, type /help to list commands" << endl;

	while(1){
		cout << "word: ";
		cin.get(word, MAX_WORD_LEN_2, '\n');
		cin.ignore(1, '\n');
		if(cin.eof())
			break;
		if(strlen(word) == 0)
			continue;

		switch(check_word((char *)&word)){
			case 0:	// normal word to translate
				if(!dict->findWord(word, &translation)){
					cout << "word not found." << endl;
					if(exact_match){
						//cout << endl;
						break;
					}
				}

				if (translation[0] != '\0') {
					cout << translation;
				}
				break;
			case 1:	// help
				cout << "These are the allowed commands:" << endl << endl;
				cout << "/help\t\tThis help screen" << endl;
				cout << "/status\t\tShow the status of the dictionary settings" << endl;
				cout << "/separated\tToggle on/off the flag for separated meanings" << endl;
				cout << "/latinin\tToggle on/off the flag for latin input" << endl;
				cout << "/latinout\tToggle on/off the flag for latin output" << endl;
				cout << "/web\t\tToggle on/off the flag for HTML output" << endl;
				cout << "/exact\tToggle on/off the flag for exact match" << endl;
				cout << "/quit\t\tQuit the program" << endl << endl;
				cout << "To translate a word just type it and press <Enter>" << endl;
				break;
			case 2:	// status
				cout << "These are the effective settings:" << endl << endl;
				cout << "Separated meanings:\t" << msg_onoff[dict->separateMeanings] << endl;
				cout << "Latin input:\t\t" << msg_onoff[dict->latinInput] << endl;
				cout << "Latin output:\t\t" << msg_onoff[dict->latinOutput] << endl;
				cout << "HTML output:\t\t" << msg_onoff[dict->htmlOutput] << endl;
				cout << "Exact match:\t\t" << msg_onoff[exact_match] << endl;
				break;
			case 3: // separate
				dict->separateMeanings = !dict->separateMeanings;
				cout << "Separated meanings are now - " << msg_onoff[dict->separateMeanings] << endl;
				break;
			case 4: // latinin
				dict->latinInput = !dict->latinInput;
				cout << "Latin input is now - " << msg_onoff[dict->latinInput] << endl;
				break;
			case 5: // latinout
				dict->latinOutput = !dict->latinOutput;
				cout << "Latin output is now - " << msg_onoff[dict->latinOutput] << endl;
				break;
			case 6: // html
				dict->htmlOutput = !dict->htmlOutput;
				cout << "HTML output is now - " << msg_onoff[dict->htmlOutput] << endl;
				break;
			case 7: // exact
				exact_match = !exact_match;
				cout << "Exact match is now - " << msg_onoff[exact_match] << endl;
				break;
			case 8: // quit
				return 0;
			case 100:
				cout << "The numbers say that you are lucky today :)" << endl;
				break;
			default:
				cout << "internal error :), bye for now" << endl;
				return 1;
		} // switch
		cout << endl;

	} // while

	return 0;
}

/////////////////////////////////////////////////////////////////////////////

int check_word(const char *word)
{
	if(*word++ != '/'){
		return 0;
	} else {
		if(!strncasecmp("help", word, 4)){
			return 1; // help
		} else if(!strncasecmp("status", word, 6)){
			return 2; // status
		} else if(!strncasecmp("separ", word, 5)){
			return 3; // separated meanings
		} else if(!strncasecmp("latinin", word, 7)){
			return 4; // latin input
		} else if(!strncasecmp("latinout", word, 8)){
			return 5; // latin output
		} else if(!strncasecmp("web", word, 3)){
			return 6; // web output
		} else if(!strncasecmp("exact", word, 5)){
			return 7; // exact match
		} else if(!strncasecmp("quit", word, 4)){
			return 8; // quit
		}
	}

	return 100; // unknown
}

/////////////////////////////////////////////////////////////////////////////

void cbeconfig()
{
    char parameter;
    char **msg = NULL;

    cout << "configuration utility:" << endl << endl;

    // select language
    msg = select_language();

    while(1) {
	parameter = 0;
	cout << endl;
        cout << "1) " << msg[MSG_SEPARATE_MEANINGS] << " - " << msg[separate_meanings] << endl;
        cout << "2) " << msg[MSG_LATIN_INPUT] << " - " << msg[latin_input] << endl;
        cout << "3) " << msg[MSG_LATIN_OUTPUT] << " - " << msg[latin_output] << endl;
        cout << "4) " << msg[MSG_HTML_OUTPUT] << " - " << msg[html_output] << endl;
	cout << "5) " << msg[MSG_EXACT_MATCH] << " - " << msg[exact_match] << endl;
	cout << "6) " << msg[MSG_START_INTERACTIVE] << " - " << msg[start_interactive] << endl;
	cout << "7) " << msg[MSG_ENG_BUL_DAT] << " - " << en_bg_filename << endl;
	cout << "8) " << msg[MSG_BUL_ENG_DAT] << " - " << bg_en_filename << endl << endl;
	cout << "s) " << msg[MSG_SAVE_AND_QUIT] << endl;
	cout << "q) " << msg[MSG_QUIT_WITHOUT_SAVE] << endl << endl;
	cout << msg[MSG_CHANGE_OPTION] << ": ";

	cin >> parameter;

	switch (parameter){
	case '1':
	    separate_meanings = !separate_meanings;
	    break;
	case '2':
	    latin_input = !latin_input;
	    break;
	case '3':
	    latin_output = !latin_output;
	    break;
	case '4':
	    html_output = !html_output;
	    break;
	case '5':
	    exact_match = !exact_match;
	    break;
	case '6':
	    start_interactive = !start_interactive;
	    break;
	case '7':
	    cout << endl << msg[MSG_PROMPT_EN_BG_CHANGE] << ": ";
	    cin.ignore(1, '\n');
	    cin.getline(en_bg_filename, FILENAME_LENGTH);
	    break;
	case '8':
	    cout << endl << msg[MSG_PROMPT_BG_EN_CHANGE] << ": ";
	    cin.ignore(1, '\n');
	    cin.getline(bg_en_filename, FILENAME_LENGTH);
	    break;
	case 's':
	case 'S':
	    reg->setString(OPTION_ENG_BUL_DAT, en_bg_filename);
	    reg->setString(OPTION_BUL_ENG_DAT, bg_en_filename);
	    reg->setBool(OPTION_SEPARATE_MEANINGS, separate_meanings);
	    reg->setBool(OPTION_LATIN_INPUT, latin_input);
	    reg->setBool(OPTION_LATIN_OUTPUT, latin_output);
	    reg->setBool(OPTION_HTML_OUTPUT, html_output);
	    reg->setBool(OPTION_EXACT_MATCH, exact_match);

	    cout << msg[MSG_CONFIG_SAVED] << endl;
	    cout << msg[MSG_QUITTING] << endl;
	    return;
	case 'q':
	case 'Q':
	    cout << msg[MSG_QUITTING] << endl;
	    return;
	default:
	    cout << msg[MSG_INCORRECT_OPTION_INDEX] << endl;
	}; // switch
    }; // while

} // main
