//
// Copyright (C) 1999-2004 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <WScom.h>
#include <WSClocaleSet.h>
#include <WSDenv.h>


static WSDcodeConvert* _the_app_code_convert = NULL;
static WSDcodeConvert* (*_c_handler)() = NULL;
WSDcodeConvert* WSGIappCodeConvert(){
  if ( _the_app_code_convert == NULL){
    if ( _c_handler == NULL){
      printf("ERROR: WSDcodeConvert create global instance..\n");
#ifdef DEBUG_TRAP
assert(0);
#endif
    }
    _the_app_code_convert = _c_handler();
  }
  return _the_app_code_convert;
}
void WSDcodeConvert::_set_code_convert_handler(WSDcodeConvert*(*hd)()){
  _c_handler = hd;
}
static WSClocaleSet* _the_app_locale_list = NULL;
WSClocaleSet* WSGIappLocaleSet(){
  if (_the_app_locale_list == NULL){
    _the_app_locale_list = new WSClocaleSet();
  }
  return _the_app_locale_list;
}

WSClocaleSet::WSClocaleSet(){
  _default_locale = NULL;
  _init = False;
  _encoding = WS_EN_LOCALE;
//  _executed = False;
}
#if 0
void WSClocaleSet::addInitializeProc(void(*hd)()){
  if (_executed == False){
    _init_procs.add((void*)hd);
  }else{
    hd();
  }
}
void WSClocaleSet::execInitializeProcs(){
  long num = _init_procs.getNum();
  long i;
  for(i=0; i<num; i++){
    void(*hd)() = (void(*)())_init_procs[i];
    hd();
  }
  _executed = False;
}
#endif
WSClocaleSet::~WSClocaleSet(){
  long num = _locale_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSClocale* locale = (WSClocale*)_locale_list[i];
    if (locale != NULL){
      delete locale;
    }
  }
}

void WSClocaleSet::initialize(){
  if (_init != False){
    return;
  }

  _init = True;
  long locale_value = WSGIappCodeConvert()->getSystemLocale();

  if (locale_value == WS_EN_NONE){
fprintf(stderr,"ERROR: LANG not supported... using locale=C.\n");
    locale_value = WS_EN_ISO8859_1;
  }
//printf("WSClocaleSet::initialize systemlocale=%s\n",WSGFgetLocaleName(locale_value));
  long i;
  long num = _locale_list.getNum();
  for(i=0; i<num; i++){
    WSClocale* locale = (WSClocale*)_locale_list[i];
    if (locale != NULL && !strcmp(locale->getLocaleName(),WSGFgetLocaleName(locale_value))){
      _default_locale = locale;
      break;
    }
  }
  if (_default_locale == NULL){
    _default_locale = new WSClocale();
    _default_locale->setLocaleName(WSGFgetLocaleName(locale_value));
    _locale_list.add((void*)_default_locale);
  }
}
char* WSClocaleSet::getDefaultLocaleName(){
  if (_init == False){
    initialize();
  }
  if (_default_locale == NULL){
    return WSN_EN_ISO8859_1;
  }

//printf("WSClocaleSet::getDefaultLocaleName() 0x%x\n",_default_locale);
//printf("WSClocaleSet::getDefaultLocaleName() 0x%x\n",_default_locale->getLocaleName());
//printf("WSClocaleSet::getDefaultLocaleName() #%s#\n",_default_locale->getLocaleName());
  return _default_locale->getLocaleName();
}

WSClocale* WSClocaleSet::getDefaultLocale(){
  if (_init == False){
    initialize();
  }
  return _default_locale;
}
long WSClocaleSet::setDefaultLocale(char* locale_str){
  long num = _locale_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSClocale* locale = (WSClocale*)_locale_list[i];
    if (locale != NULL && !strcmp(locale->getLocaleName(),locale_str)){
      _default_locale = locale;
      return WS_NO_ERR;
    }
  }
  _default_locale = new WSClocale();
  _default_locale->setLocaleName(locale_str);
  _locale_list.add((void*)_default_locale);
  return WS_NO_ERR;
}
WSClocale* WSClocaleSet::getLocale(char* locale_str){
  long num = _locale_list.getNum();
  long i;
  for(i=0; i<num; i++){
    WSClocale* locale = (WSClocale*)_locale_list[i];
    if (locale != NULL && !strcmp(locale->getLocaleName(),locale_str)){
      return locale;
    }
  }
  return NULL;
}
void WSClocaleSet::setLocaleString(char* locale_str,char* index,char* str){
  WSClocale* locale = getLocale(locale_str);
//printf("WSClocaleSet::setLocaleString locale=0x%x\n",locale);
  if (locale == NULL){
    locale = new WSClocale();
    locale->setLocaleName(locale_str);
    _locale_list.add((void*)locale);
  }
//printf("WSClocaleSet::setLocaleString loc=%s index=%s\n",locale_str,index);
  locale->setString(index,str);
}
char* WSClocaleSet::getLocaleString(char* locale_str,char* index,long encode){
  WSClocale* locale = getLocale(locale_str);
  if (locale == NULL){
    return locale_str;
  }
  return locale->getString(index,encode);
}
WSClocale::WSClocale(){
//printf("this=0x%x\n",this);
  _locale = WS_EN_NONE;
  long i;
  for(i=0; i<WS_MAX_HASH_VALUE; i++){
    _hash[i] = NULL;
  }
}
WSClocale::~WSClocale(){
  long i;
  for(i=0; i<WS_MAX_HASH_VALUE; i++){
    if (_hash[i] != NULL){
      WSCindexData* list = (WSCindexData*)_hash[i];
      long num = list->getNum();
      long j;
      for(j=0; j<num; j++){
        WSCstring* item = (WSCstring*)list->getData(j);
        delete item;
      }
      delete list;
    }
  }
}
void WSClocale::setLocaleName(char* lname){
//printf("this=0x%x\n",this);
//printf("WSClocale::setLocaleName #%s#\n",lname);
  _locale = WSGFgetLocaleValue(lname);
  if (_locale == WS_EN_NONE){
//printf("WSClocale::setString Error encoding=%s not found.\n",index);
    _locale = WS_EN_ISO8859_1; 
  }
//printf("_locale=%d name=%s\n",_locale,WSGFgetLocaleName(_locale));
  _name.setString(lname);
}

char* WSClocale::getLocaleName(){
  return (char*)_name;
}
void WSClocale::setString(char* index,char* str){
//printf("this=0x%x\n",this);
  long val = WSGFgetHashValue(index);
  WSCindexData* list = _hash[val];
  if (list == NULL){
    list = new WSCindexData();
    _hash[val] = list;
  }
  WSCstring* str2 = new WSCstring;
//printf("setstring _locale=%d name=%s\n",_locale,WSGFgetLocaleName(_locale));
  str2->setString(str,_locale);
  list->setData(index,str2);
//printf("this=0x%x index=%s str=%s list=0x%x hash=%d\n",this,index,str,list,val);
}
char* WSClocale::getString(char* index,long encode){
  long val = WSGFgetHashValue(index);

  WSCindexData* list = _hash[val];
//printf("this=0x%x index=%s list=0x%x hash=%d\n",this,index,list,val);
  if (list == NULL){
    WSCstring tmp(index);
    if (tmp.isExist(":WSSTR") <0){
    }else{
      if (!strcmp(getLocaleName(),"UTF8")){
        WSClocale* locale = WSGIappLocaleSet()->getLocale(WSN_EN_ISO8859_1);
        if (locale != NULL){
          return locale->getString(index,encode);
        }
fprintf(stderr,"WSClocale::getString locale=%s index=%s not found.\n",getLocaleName(),index);
      }
    }
    return index;
  }
  WSCstring* ret = (WSCstring*)list->getData(index);
  if (ret == NULL){
    WSCstring tmp(index);
    if (tmp.isExist(":WSSTR") <0){
    }else{
      WSClocale* locale = WSGIappLocaleSet()->getLocale(WSN_EN_ISO8859_1);
      if (locale != NULL){
        return locale->getString(index,encode);
      }
fprintf(stderr,"WSClocale::getString locale=%s index=%s not found.\n",getLocaleName(),index);
    }
    return index;
  }
  return ret->getString(encode);
}
char* WSGFgettext(char* index){
//printf("WSGFgettext index=%s\n",index);
  WSClocale* locale = WSGIappLocaleSet()->getDefaultLocale();
  if (locale == NULL){
fprintf(stderr,"ERROR. WSGFgettext default locale does not found. use locale=C\n");
    locale = WSGIappLocaleSet()->getLocale(WSN_EN_ISO8859_1);
    if (locale == NULL){
fprintf(stderr,"ERROR. WSGFgettext locale C does not found.\n");
      return index;
    }
  }
//  return locale->getString(index,WSGIappLocaleSet()->getSystemLocaleEncoding());

  return locale->getString(index,WSGIappLocaleSet()->getDefaultEncoding());
}
long WSClocaleSet::getSystemLocaleEncoding(){
  return WSGIappCodeConvert()->getSystemLocale();
}
long WSClocaleSet::getDefaultEncoding(){
  if (_encoding == WS_EN_LOCALE){
    return WSGIappCodeConvert()->getSystemLocale();
  }
  return _encoding;
}
void WSClocaleSet::setDefaultEncoding(long encoding){
  _encoding = encoding;
}
void WSGFsetDefaultEncoding(long en){
  WSGIappLocaleSet()->setDefaultEncoding(en);
}
