/*
 *   Copyright (C) 2000-2003 TR-IRCD Development
 *
 *   Copyright (C) 1990 Jarkko Oikarinen and
 *                      University of Oulu, Co Center
 *
 *   Numerous fixes by Markku Savela
 *
 *   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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 * $Id: s_numeric.c,v 1.3 2003/06/14 13:55:52 tr-ircd Exp $ 
 */

#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "channel.h"
#include "language.h"
#include "h.h"

static char buffer[1024];

static struct LangHash *lang_hash_table[MAX_LANG_HASH];

static int standardindex = 0;

static char *en_us = "en_us";

/*
 * hash
 *
 * inputs       - char string
 * output       - hash index
 * side effects - NONE
 *
 * BUGS         - This a HORRIBLE hash function
 */
static int hash(char *p)
{
    int hash_val = 0;

    while (*p) {
	hash_val += ((int) (*p) & 0xDF);
	p++;
    }

    return (hash_val % MAX_LANG_HASH);
}

int clear_hash_lang()
{
    memset(lang_hash_table, 0, sizeof(lang_hash_table));
    lang_add_table("standard", "en_us", replies);
    lang_add_table("english", "en_us", replies);
    standardindex = hash("english");
    return 0;
}

void lang_add_table(char *langname, char *helpdir, char **fmtarray)
{
    struct LangHash *ptr;
    struct LangHash *last_ptr = NULL;
    struct LangHash *new_ptr;
    int langindex;

    langindex = hash(langname);

    for (ptr = lang_hash_table[langindex]; ptr; ptr = ptr->next) {
	if (irc_strcmp(langname, ptr->langname) == 0)
	    return;		/* Its already added */
	last_ptr = ptr;
    }

    new_ptr = (struct LangHash *) MyMalloc(sizeof(struct LangHash));

    new_ptr->next = NULL;
    DupString(new_ptr->langname, langname);
    DupString(new_ptr->helpdirname, helpdir);
    new_ptr->fmtarray = fmtarray;

    if (last_ptr == NULL)
	lang_hash_table[langindex] = new_ptr;
    else
	last_ptr->next = new_ptr;
}

void lang_del_table(char *langname)
{
    struct LangHash *ptr;
    struct LangHash *last_ptr = NULL;
    int langindex;

    langindex = hash(langname);

    for (ptr = lang_hash_table[langindex]; ptr; ptr = ptr->next) {
	if (irc_strcmp(langname, ptr->langname) == 0) {
	    MyFree(ptr->langname);
	    MyFree(ptr->helpdirname);
	    if (last_ptr != NULL)
		last_ptr->next = ptr->next;
	    else
		lang_hash_table[langindex] = ptr->next;
	    ptr->fmtarray = NULL;
	    MyFree(ptr);
	    return;
	}
    }
}

int lang_parse(char *givenname)
{
    struct LangHash *ptr;
    int langindex;

    langindex = hash(givenname);
    for (ptr = lang_hash_table[langindex]; ptr; ptr = ptr->next) {
	if (irc_strcmp(givenname, ptr->langname) == 0) {
	    return langindex;
	}
    }
    return 0;
}

char **get_language(int langindex)
{
    struct LangHash *ptr;

    if (langindex) {
	ptr = lang_hash_table[langindex];
	if (ptr)
	    return ptr->fmtarray;
    } else if (me.lang) {
	ptr = lang_hash_table[me.lang];
	if (ptr)
	    return ptr->fmtarray;
    }

    return replies;		/* standard english */
}

int set_language(int langindex)
{

    if (langindex) {
	if (lang_hash_table[langindex])
	    return langindex;
    }
    return standardindex;
}

char *get_langpath(aClient *cptr)
{
    struct LangHash *ptr;
    int langindex;

    langindex = cptr->lang;
    if (langindex) {
	ptr = lang_hash_table[langindex];
	if (ptr)
	    return ptr->helpdirname;
    } else if (me.lang) {
	ptr = lang_hash_table[me.lang];
	if (ptr)
	    return ptr->helpdirname;
    }

    return en_us;
}
    

char *rpl_str(int numeric)
{
    if ((numeric < 0 || numeric > 999) || !replies[numeric])
	return (replies[ERR_NUMERIC_ERR]);
    else
	return (replies[numeric]);
}

/* This hack here searches for the given numeric
 * in the language array. If it is not available, then the default
 * array is used. -TimeMr14C */

char *get_numeric_format_in_lang(int *numeric, char **replylist)
{
    if ((*numeric < 0 || *numeric > 999) || !replylist[*numeric]) {
	if (!replies[*numeric]) {
	    *numeric = ERR_NUMERIC_ERR;
	    return replies[ERR_NUMERIC_ERR] + 11;
	} else
	    return replies[*numeric] + 11;
    } else
	return replylist[*numeric] + 11;
}

void list_languages(aClient *cptr)
{
    int i;
    struct LangHash *ptr;

    send_me_notice(cptr, ":Available languages");
    for (i = 0; i < MAX_LANG_HASH; i++) {
	for (ptr = lang_hash_table[i]; ptr; ptr = ptr->next)
	    send_me_notice(cptr, ":%s", ptr->langname);
    }
    send_me_notice(cptr, ":End of language list");
}

/*
 * * DoNumeric (replacement for the old do_numeric) *
 * 
 *      parc    number of arguments ('sender' counted as one!) *
 * parv[0]      pointer to 'sender' (may point to empty string) (not
 * used) *      parv[1]..parv[parc-1] *         pointers to additional
 * parameters, this is a NULL *         terminated list (parv[parc] ==
 * NULL). *
 * 
 * *WARNING* *  Numerics are mostly error reports. If there is
 * something *  wrong with the message, just *DROP* it! Don't even
 * think of *   sending back a neat error message -- big danger of
 * creating *   a ping pong error message...
 */
int do_numeric(int numeric, aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    aClient *acptr;
    int i;

    if (parc < 1 || (!IsServer(sptr) && !IsService(sptr)))
	return 0;

    /*
     * Remap low number numerics. 
     * WHAT THE HELL DOES THIS ???
     * -TimeMr14C
     * if (numeric < 100)
     *  numeric += 100;
     */

    /*
     * * Prepare the parameter portion of the message into 'buffer'. *
     * (Because the buffer is twice as large as the message buffer * for
     * the socket, no overflow can occur here... ...on current *
     * assumptions--bets are off, if these are changed --msa) * Note: if
     * buffer is non-empty, it will begin with SPACE.
     */

    buffer[0] = '\0';
    if (parc > 1) {
	for (i = 2; i < (parc - 1); i++) {
	    strcat(buffer, " ");
	    strcat(buffer, parv[i]);
	}
	strcat(buffer, " :");
	strcat(buffer, parv[parc - 1]);
    }

    if ((acptr = find_client(parv[1]))) {

	if (IsMe(acptr))
	    return 0;
	else if (acptr->from == cptr)
	    return 0;
	else if (MyClient(acptr) && !IsAnOper(acptr))
	    sendto_one(acptr, ":%*C %N %~C%s", sptr, numeric, acptr, buffer);
	else
	    sendto_one(acptr, ":%C %N %~C%s", sptr, numeric, acptr, buffer);
    }

    return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1