/*
 * The contents of this file are subject to the Netscape Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/NPL/
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code is Mozilla Communicator client code, released
 * March 31, 1998.
 *
 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation. Portions created by Netscape are
 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
 * Rights Reserved.
 *
 * Contributor(s):
 */

var gMisspelledWord;
var spellChecker;
var allowSelectWord = true;
var PreviousReplaceWord = "";
var firstTime = true;

// dialog initialization code
function Startup()
{
  if (!InitEditorShell())
    return;

  // Get the spellChecker shell
  spellChecker = editorShell.QueryInterface(Components.interfaces.nsIEditorSpellCheck);
  if (!spellChecker) {
    dump("SpellChecker not found!!!\n");
    window.close();
    return;
  }

  // Start the spell checker module.
  try {
   spellChecker.InitSpellChecker();

   // XXX: We need to read in a pref here so we can set the
   //      default language for the spellchecker!
   // spellChecker.SetCurrentDictionary();
  }
  catch(ex) {
   dump("*** Exception error: InitSpellChecker\n");
    window.close();
    return;
  }

  gDialog.MisspelledWordLabel = document.getElementById("MisspelledWordLabel");
  gDialog.MisspelledWord      = document.getElementById("MisspelledWord");
  gDialog.ReplaceButton       = document.getElementById("Replace");
  gDialog.IgnoreButton        = document.getElementById("Ignore");
  gDialog.CloseButton         = document.getElementById("Close");
  gDialog.ReplaceWordInput    = document.getElementById("ReplaceWordInput");
  gDialog.SuggestedList       = document.getElementById("SuggestedList");
  gDialog.LanguageMenulist    = document.getElementById("LanguageMenulist");

  // Fill in the language menulist and sync it up
  // with the spellchecker's current language.

  var curLang;

  try {
    curLang = spellChecker.GetCurrentDictionary();
  } catch(ex) {
    curLang = "";
  }

  InitLanguageMenu(curLang);

  SetWindowLocation();

  // Get the first misspelled word and setup all UI
  NextWord();

  // Clear flag that determines message when
  //  no misspelled word is found
  //  (different message when used for the first time)
  firstTime = false;
}

function InitLanguageMenu(curLang)
{

  var o1 = {};
  var o2 = {};

  // Get the list of dictionaries from
  // the spellchecker.

  try {
    spellChecker.GetDictionaryList(o1, o2);
  } catch(ex) {
    dump("Failed to get DictionaryList!\n");
    return;
  }

  var dictList = o1.value;
  var count    = o2.value;

  // Load the string bundles that will help us map
  // RFC 1766 strings to UI strings.

  var languageBundle;
  var regionBundle;
  var menuStr2;
  var isoStrArray;
  var defaultIndex = 0;
  var langId;

  // Try to load the language string bundle.

  try {
    languageBundle = srGetStrBundle("chrome://global/locale/languageNames.properties");
  } catch(ex) {
    languageBundle = null;
  }

  // If we have a language string bundle, try to load the region string bundle.

  if (languageBundle)
  {
    try {
      regionBundle = srGetStrBundle("chrome://global/locale/regionNames.properties");
    } catch(ex) {
      regionBundle = null;
    }
  }
  var i;
  for (i = 0; i < dictList.length; i++)
  {
    try {
      langId = dictList[i];
      isoStrArray = dictList[i].split("-");

      dictList[i] = new Array(2); // first subarray element - pretty name
      dictList[i][1] = langId;    // second subarray element - language ID

      if (languageBundle && isoStrArray[0])
        dictList[i][0] = languageBundle.GetStringFromName(isoStrArray[0].toLowerCase());

      if (regionBundle && dictList[i][0] && isoStrArray.length > 1 && isoStrArray[1])
      {
        menuStr2 = regionBundle.GetStringFromName(isoStrArray[1].toLowerCase());
        if (menuStr2)
          dictList[i][0] = dictList[i][0] + "/" + menuStr2;
      }

      if (!dictList[i][0])
        dictList[i][0] = dictList[i][1];
    } catch (ex) {
      // GetStringFromName throws an exception when
      // a key is not found in the bundle. In that
      // case, just use the original dictList string.

      dictList[i][0] = dictList[i][1];
    }
  }
  
  // note this is not locale-aware collation, just simple ASCII-based sorting
  // we really need to add loacel-aware JS collation, see bug XXXXX
  dictList.sort();

  for (i = 0; i < dictList.length; i++)
  {
    AppendLabelAndValueToMenulist(gDialog.LanguageMenulist, dictList[i][0], dictList[i][1]);
    if (curLang && dictList[i][1] == curLang)
      defaultIndex = i+2; //first two items are pre-populated and fixed
  }

  // Now make sure the correct item in the menu list is selected.

  if (dictList.length > 0)
    gDialog.LanguageMenulist.selectedIndex = defaultIndex;
}

function DoEnabling()
{
  if (!gMisspelledWord)
  {
    // No more misspelled words
    gDialog.MisspelledWord.setAttribute("value",GetString( firstTime ? "NoMisspelledWord" : "CheckSpellingDone"));

    gDialog.ReplaceButton.removeAttribute("default");
    gDialog.IgnoreButton.removeAttribute("default");

    gDialog.CloseButton.setAttribute("default","true");
    // Shouldn't have to do this if "default" is true?
    gDialog.CloseButton.focus();

    SetElementEnabledById("MisspelledWordLabel", false);
    SetElementEnabledById("ReplaceWordLabel", false);
    SetElementEnabledById("ReplaceWordInput", false);
    SetElementEnabledById("CheckWord", false);
    SetElementEnabledById("SuggestedListLabel", false);
    SetElementEnabledById("SuggestedList", false);
    SetElementEnabledById("Ignore", false);
    SetElementEnabledById("IgnoreAll", false);
    SetElementEnabledById("Replace", false);
    SetElementEnabledById("ReplaceAll", false);
    SetElementEnabledById("AddToDictionary", false);

    // Signal to calling window that we're done
    window.opener.spellCheckCompleted = true;
  } else {
    SetElementEnabledById("MisspelledWordLabel", true);
    SetElementEnabledById("ReplaceWordLabel", true);
    SetElementEnabledById("ReplaceWordInput", true);
    SetElementEnabledById("CheckWord", true);
    SetElementEnabledById("SuggestedListLabel", true);
    SetElementEnabledById("SuggestedList", true);
    SetElementEnabledById("Ignore", true);
    SetElementEnabledById("IgnoreAll", true);
    SetElementEnabledById("AddToDictionary", true);

    gDialog.CloseButton.removeAttribute("default");
    SetReplaceEnable();

    // Signal to calling window that we're not done
    window.opener.spellCheckCompleted = false;
  }
}

function NextWord()
{
  gMisspelledWord = spellChecker.GetNextMisspelledWord();
  SetWidgetsForMisspelledWord();
}

function SetWidgetsForMisspelledWord()
{
  gDialog.MisspelledWord.setAttribute("value", gMisspelledWord);


  // Initial replace word is misspelled word
  gDialog.ReplaceWordInput.value = gMisspelledWord;
  PreviousReplaceWord = gMisspelledWord;

  // This sets gDialog.ReplaceWordInput to first suggested word in list
  FillSuggestedList(gMisspelledWord);

  DoEnabling();

  if (gMisspelledWord)
    SetTextboxFocus(gDialog.ReplaceWordInput);
}

function CheckWord()
{
  word = gDialog.ReplaceWordInput.value;
  if (word) 
  {
    isMisspelled = spellChecker.CheckCurrentWord(word);
    if (isMisspelled)
    {
      FillSuggestedList(word);
      SetReplaceEnable();
    } 
    else 
    {
      ClearTreelist(gDialog.SuggestedList);
      var item = AppendStringToTreelistById(gDialog.SuggestedList, "CorrectSpelling");
      if (item) item.setAttribute("disabled", "true");
      // Suppress being able to select the message text
      allowSelectWord = false;
    }
  }
}

function SelectSuggestedWord()
{
  if (allowSelectWord)
  {
    var index = gDialog.SuggestedList.selectedIndex;
    if (index == -1)
    {
      gDialog.ReplaceWordInput.value = PreviousReplaceWord;
    }
    else
    {
      var selValue = GetSelectedTreelistValue(gDialog.SuggestedList);
      gDialog.ReplaceWordInput.value = selValue;
      PreviousReplaceWord = selValue;
    }
    SetReplaceEnable();
  }
}

function ChangeReplaceWord()
{
  // Calling this triggers SelectSuggestedWord(),
  //  so temporarily suppress the effect of that
  var saveAllow = allowSelectWord;
  allowSelectWord = false;

  // Select matching word in list
  var newIndex = -1;
  var replaceWord = TrimString(gDialog.ReplaceWordInput.value);
  if (replaceWord)
  {
    var count = 0;
    var treeChildren = gDialog.SuggestedList.firstChild.nextSibling;
    if (treeChildren && treeChildren.childNodes)
      count = treeChildren.childNodes.length;

    for (var i = 0; i < count; i++)
    {
      var wordInList = GetTreelistValueAt(gDialog.SuggestedList, i);
      if (wordInList == replaceWord)
      {
        newIndex = i;
        break;
      }
    }
  }
  gDialog.SuggestedList.selectedIndex = newIndex;

  allowSelectWord = saveAllow;

  // Remember the new word
  PreviousReplaceWord = gDialog.ReplaceWordInput.value;

  SetReplaceEnable();
}

function Ignore()
{
  NextWord();
}

function IgnoreAll()
{
  if (gMisspelledWord) {
    spellChecker.IgnoreWordAllOccurrences(gMisspelledWord);
  }
  NextWord();
}

function Replace()
{
  var newWord = gDialog.ReplaceWordInput.value;
  if (gMisspelledWord && gMisspelledWord != newWord)
  {
    editorShell.BeginBatchChanges();
    var isMisspelled = spellChecker.ReplaceWord(gMisspelledWord, newWord, false);
    editorShell.EndBatchChanges();
  }
  NextWord();
}

function ReplaceAll()
{
  var newWord = gDialog.ReplaceWordInput.value;
  if (gMisspelledWord && gMisspelledWord != newWord)
  {
    editorShell.BeginBatchChanges();
    isMisspelled = spellChecker.ReplaceWord(gMisspelledWord, newWord, true);
    editorShell.EndBatchChanges();
  }
  NextWord();
}

function AddToDictionary()
{
  if (gMisspelledWord) {
    spellChecker.AddWordToDictionary(gMisspelledWord);
  }
  NextWord();
}

function EditDictionary()
{
  window.openDialog("chrome://editor/content/EdDictionary.xul", "_blank", "chrome,close,titlebar,modal", "", gMisspelledWord);
}

function SelectLanguage()
{
  try {
    var item = gDialog.LanguageMenulist.selectedItem;
    if (item.value != "more-cmd")
      spellChecker.SetCurrentDictionary(item.value);
    else
      window.openDialog( getBrowserURL(), "_blank", "chrome,all,dialog=no,modal", xlateURL('urn:clienturl:composer:spellcheckers'));
  } catch (ex) {
    dump(ex);
  }
}

function Recheck()
{
  //TODO: Should we bother to add a "Recheck" method to interface?
  try {
    var curLang = spellChecker.GetCurrentDictionary();

    spellChecker.UninitSpellChecker();
    spellChecker.InitSpellChecker();
    spellChecker.SetCurrentDictionary(curLang);
    gMisspelledWord = spellChecker.GetNextMisspelledWord();
    SetWidgetsForMisspelledWord();
  } catch(ex) {
    dump(ex);
  }
}

function FillSuggestedList(misspelledWord)
{
  var list = gDialog.SuggestedList;

  // Clear the current contents of the list
  allowSelectWord = false;
  ClearTreelist(list);
  var item;

  if (misspelledWord.length > 0)
  {
    // Get suggested words until an empty string is returned
    var count = 0;
    var firstWord = 0;
    do {
      var word = spellChecker.GetSuggestedWord();
      if (count==0)
        firstWord = word;
      if (word.length > 0) {
        AppendStringToTreelist(list, word);
        count++;
      }
    } while (word.length > 0);

    var len = list.getAttribute("length");

    if (count == 0)
    {
      // No suggestions - show a message but don't let user select it
      item = AppendStringToTreelistById(list, "NoSuggestedWords");
      if (item) item.setAttribute("disabled", "true");
      allowSelectWord = false;
    } else {
      allowSelectWord = true;
      // Initialize with first suggested list by selecting it
      gDialog.SuggestedList.selectedIndex = 0;
    }
  } 
  else
  {
    item = AppendStringToTreelist(list, "");
    if (item)
      item.setAttribute("disabled", "true");
  }
}

function SetReplaceEnable()
{
  // Enable "Change..." buttons only if new word is different than misspelled
  var newWord = gDialog.ReplaceWordInput.value;
  var enable = newWord.length > 0 && newWord != gMisspelledWord;
  SetElementEnabledById("Replace", enable);
  SetElementEnabledById("ReplaceAll", enable);
  if (enable)
  {
    gDialog.ReplaceButton.setAttribute("default","true");
    gDialog.IgnoreButton.removeAttribute("default");
  }
  else
  {
    gDialog.IgnoreButton.setAttribute("default","true");
    gDialog.ReplaceButton.removeAttribute("default");
  }
}

function doDefault()
{
  if (gDialog.ReplaceButton.getAttribute("default") == "true")
    Replace();
  else if (gDialog.IgnoreButton.getAttribute("default") == "true")
    Ignore();
  else if (gDialog.CloseButton.getAttribute("default") == "true")
    return onClose();

  // Don't close the dialog
  return false;
}

function onClose()
{
  // Shutdown the spell check and close the dialog
  spellChecker.UninitSpellChecker();
  return onCancel();
}

