{
    This file is part of Chentrah,
    Copyright (C) 2004-2008 Anton Rzheshevski (chebmaster@mail.ru).

    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, see http://www.gnu.org/licenses/

 **********************************************************************}

  constructor TMessageContainer.Create;
  var
    mi: TMessageId;
  begin
    inherited Create;
    SetLength(LID, 2);
    SetLength(M, 2);
    LID[0]:='RU_RU';
    LID[1]:='EN_US';
    SubstituteLang:= 1;
    CurrentLang:= -1;
    for mi:=low(TMessageID) to pred(MI_LAST_BUILTIN_MESSAGE) do begin
      M[0, mi]:= BuiltInRussianMessages[mi];
      M[1, mi]:= BuiltInEnglishMessages[mi]
    end;
    for mi:= MI_LAST_BUILTIN_MESSAGE to high(TMessageID) do begin
      M[0, mi]:= '<MESSAGE TEXT NOT AVAILABLE>';
      M[1, mi]:= '<MESSAGE TEXT NOT AVAILABLE>';
    end;
    CgeString:=M[1, MI_CGE_TITLE];
  end;

  procedure TMessageContainer.LoadFiles;
  var
    str, sp, extra, ls, ms: string;
    i, LN, n: integer;
    il: TFileList;
    mi: TMessageId;
    sl: TStringList;
    ws: WideString;
  begin
    Try
      str:=Config.Str['language', 'list'];
      if MotherState.VerboseLog then AddLog('Loading translations for language id="%0"...',[str]);
      i:=1;
      While StrParm(str, i, [',']) <> '' do begin
        sp:= uppercase(Trim(StrParm(str, i, [','])));
        if ((i = 1) and (sp <> 'RU_RU')) or ((i = 2) and (sp <> 'EN_US'))
          then Die('The first two languages in the list'#10#13'  must be ru_RU and en_US. This is hard coded.');
        if i > 2 then begin
          SetLength(LID, i);
          LID[i - 1]:= sp;
          SetLength(M, i);
          for mi:=low(TMessageID) to high(TMessageID) do M[i - 1, mi]:= '';
        end;
        inc(i);
      end;
      if not DirectoryExists(MotherState.InstallPath + TranslationsDir) then
        {if i = 3
          then exit //the built-in support for Russizn and English will do
          else} Die('Folder not found,'#10#13'  ' + MotherState.InstallPath + TranslationsDir);
      try
        il:=TFileList.Create(MotherState.InstallPath + TranslationsDir + '*.chla');
        il.SortByDate;
        if il.Count = 0 then Raise Exception.Create('No files found.');
      except
        Die('Failed to build file list for'#10#13'  ' + MotherState.InstallPath + TranslationsDir + '*.chla');
      end;
      extra:='';
      for n:= 0 to il.Count - 1 do begin
        if MotherState.VerboseLog then AddLog('  ..lang. file "%0"..',[il.Names[n]]);
        sl:=TStringList.Create;
        sl.LoadFromFile(il.Names[n]);
        i:=0;
        repeat
          //first, find the section
          ms:=uppercase(sl[i]);
          if (ms > '') and (ms[1] = '#') then begin

           //then, validate the section
            LN:=high(LID);
            ls:=StrParm(ms, 1, ['#']);
            while (LN >= 0) and (ls <> LID[LN]) do dec(LN);
//dbgsay(inttostr(ln) + ' '+ ls +' ' + StrParm(ms, 2, ['#']) +  ' ' + lid[0] + ' ' + lid[1]);

            mi:= low(TMessageID);
            ms:=StrParm(ms, 2, ['#']);
            while (mi < high(TMessageID))
              and ('MI_' + ms <> GetEnumName( typeinfo(TMessageID), ord(mi) ))
              do inc(mi);
            
            if (mi = high(TMessageID)) or (mi = MI_LAST_BUILTIN_MESSAGE) or (LN < 0)
            then
              extra += #10#13'    ' + uppercase(trim(sl[i]))
            else begin
              M[LN, mi]:= '';
              while (i < sl.Count - 1) and (sl[i + 1] <> '') and (sl[i + 1][1] <> '#')
              do begin
              //last, load the section into the array.
                inc(i);
                if M[LN, mi] > ''
                  then M[LN, mi] += #10#13;
                if trim(sl[i]) <> '.'  //lines consisting of single point are considered empty
                  then M[LN, mi] += Utf8Decode(sl[i]);

              end
            end;
          end;
          inc(i)
        until i >= sl.Count;
        sl.Free;
        if extra <> '' then Die('The file'#10#13'  ' + il.Names[n] + #10#13'  contains the following invalid MIDs:' + extra);
      end;


      if MotherState.DeveloperMode then begin
        for i:=0 to 1 do begin
          sl:=TStringList.Create;
          sl.Add(' // This file is generated automatically, do not edit it!');
          sl.Add(#10#13''#10#13);
          for mi:= low(TMessageID) to pred(MI_LAST_BUILTIN_MESSAGE) do begin
            ws:= substr(M[i, mi], 1, 254);
            ws:= StrReplace(StrReplace(StrReplace(StrReplace(ws, WideString(''''), WideString('@#$%^')), WideString('@#$%^'), WideString('''''')), WideString(#10), WideString('''#10''')), WideString(#13), WideString('''#13 + '''));
                                                                  // actually this ^ just replaces ' with '' - go tell ;)
            //cl_msg_en.h(158,5) Error: Constant strings can't be longer than 255 chars
            sl.Add('    ''' + Utf8Encode(ws) + ''',');
          end;
          if i = 0
            then sl.SaveToFile(MotherState.InstallPath + 'modules/chentrah/src/cl_msg_ru.h')
            else sl.SaveToFile(MotherState.InstallPath + 'modules/chentrah/src/cl_msg_en.h');
          sl.Free;
        end;
      end;
      
    except
      SetLength(LID, 2); //fallback to the built-in languages only;
      SetLength(M, 2);
      if MotherState.DeveloperMode
        then raise Exception.Create('Unable to load translations!' + StopDying)
        else AddStopMessage('Unable to load translations!'#10#13#10#13 + StopDying());
    end;
    
    for i:=0 to high(Lid) do
      if uppercase(lid[i]) = uppercase(Config.Str['language', 'chosen'])
      then begin
        CurrentLang:= i;
        break;
      end;
    MotherState.IsRussian:= CurrentLanguage = 0;
    if MotherState.VerboseLog then AddLogOk;
  end;

  function TMessageContainer._GetMessage(index: TMessageID): WideString;
  var
    oneliner: boolean;
    i: integer;
  begin
    if CurrentLang < 0 then begin
      //the language isn't yet chosen - combine all the known ones
      if index in [MI_EXIT, MI_CHOOSE_LANG_CAPTION, MI_CHOOSE_LANG_TEXT] then  begin
        Result:= M[0, index];
        oneliner:= Pos(#13, Result) < 1;
        for i:= 1 to high(LID) do
          if oneliner
            then Result += ' / ' + M[i, index]
            else Result +=  #10#13#10#13'······································'#10#13#10#13 + M[i, index];
        end
      else Result:= M[SubstituteLang, index];
    end
    else
      Result:=M[CurrentLang, index];
  end;
  
  function TMessageContainer.GetMessage(LangInd: integer; ind: TMessageID): WideString;
  begin
    Result:=M[LangInd, ind];
    if Result='' then Result:= M[SubstituteLang, ind];
  end;

  function TMessageContainer.LanguageName(LangInd: integer): WideString;
  begin
    Result:=GetMessage(LangInd, MI_LANGUAGE_NAME);
  end;

  function TMessageContainer.LanguageName: WideString;
  begin
    Result:=LanguageName(CurrentLang);
  end;

  procedure TMessageContainer.SetLanguage(i: integer);
  begin
    CurrentLang:=i;
    if CurrentLang > high(LID)
      then CurrentLang:= -1
      else
        if i < 0
          then Config.Str['language', 'chosen']:= ''
          else Config.Str['language', 'chosen']:= LID[CurrentLang];

    CgeString:=_GetMessage(MI_CGE_TITLE);
    if i >= 0 then AddLog(MI_LANGUAGE_NAME);
    MotherState.IsRussian:= CurrentLanguage = 0;
  end;
  
  
  function TMessageContainer.NumLanguages(): integer;
  begin
    Result:=Length(LID);
  end;
  
  function TMessageContainer._ReadLid(i: integer): AnsiString;
  begin
    Result:= LID[i];
  end;



