/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla 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/MPL/
 *
 * 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 Boogie.
 *
 * The Initial Developer of the Original Code is
 * David Majda.
 * Portions created by the Initial Developer are Copyright (C) 2004-2008
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Ondrej Donek, <ondrejd@gmail.com>
 *
 * ***** END LICENSE BLOCK ***** */

const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";

const IDT_BUG        = 1;
const IDT_ENHACEMENT = 2;

var localBundle;
var prefs;

var viewIssuesBroadcaster;
var viewProjectsBroadcaster;
var viewDevelopersBroadcaster;
var viewNotesBroadcaster;
var viewReportsBroadcaster;

var issuesButton;
var projectsButton;
var developersButton;
var notesButton;

var mainDeck;

var newBugButton;
var newEnhacementButton;
var bugView;

var projectsTree;
var editProjectButton;
var deleteProjectButton;

var currentProjectHeader;

var componentListbox;
var newComponentButton;
var editComponentButton;
var deleteComponentButton;

var versionListbox;
var newVersionButton;
var editVersionButton;
var deleteVersionButton;

var developersTree;
var newDeveloperButton;
var editDeveloperButton;
var deleteDeveloperButton;

var notesTree;
var newNoteButton;
var editNoteButton;
var deleteNoteButton;

var boogieDb;

var gBoogie;

/* ----- Main window - global events ----- */

/**
 * Called when Boogie is loaded
 */
function windowLoad()
{ 
  localBundle = document.getElementById("local-bundle");
  
  gBoogie = new BoogieControllerPrototype();

  viewIssuesBroadcaster = document.getElementById("view-issues-broadcaster");
  viewProjectsBroadcaster = document.getElementById("view-projects-broadcaster");
  viewDevelopersBroadcaster = document.getElementById("view-developers-broadcaster");
  viewNotesBroadcaster = document.getElementById("view-notes-broadcaster");
  viewReportsBroadcaster = document.getElementById("view-reports-broadcaster");

  issuesButton = document.getElementById("issues-button");
  projectsButton = document.getElementById("projects-button");
  developersButton = document.getElementById("developers-button");
  notesButton = document.getElementById("notes-button");

  mainDeck = document.getElementById("main-deck");

  newBugButton = document.getElementById("new-bug-button");
  newEnhacementButton = document.getElementById("new-enhacement-button");
  bugView = document.getElementById("bug-view");

  projectsTree = document.getElementById("boogieProjectsTree");
  editProjectButton = document.getElementById("edit-project-button");
  deleteProjectButton = document.getElementById("delete-project-button");

  currentProjectHeader = document.getElementById("current-project-header");

  componentListbox = document.getElementById("component-listbox");
  newComponentButton = document.getElementById("new-component-button");
  editComponentButton = document.getElementById("edit-component-button");
  deleteComponentButton = document.getElementById("delete-component-button");

  versionListbox = document.getElementById("version-listbox");
  newVersionButton = document.getElementById("new-version-button");
  editVersionButton = document.getElementById("edit-version-button");
  deleteVersionButton = document.getElementById("delete-version-button");

  developersTree = document.getElementById("boogieDevelopersTree");
  newDeveloperButton = document.getElementById("new-developer-button");
  editDeveloperButton = document.getElementById("edit-developer-button");
  deleteDeveloperButton = document.getElementById("delete-developer-button");

  notesTree = document.getElementById("boogieNotesTree");
  newNoteButton = document.getElementById("new-note-button");
  editNoteButton = document.getElementById("edit-note-button");
  deleteNoteButton = document.getElementById("delete-note-button");
  
  // Initialize preferences
  prefs = Components.classes ["@mozilla.org/preferences-service;1"].
      getService(Components.interfaces.nsIPrefService).
      getBranch("boogie.");
  
  // Initialize boogie database service
  boogieDb = new BoogieDatabaseServicePrototype();
  if(!boogieDb.initialize()) {
    alert("Databaze initializing failed!");
  }
  
  //updateProjectsTree();
  //updateDevelopersTree();
  //updateNotesTree();
  //updateCurrentProject();
  //updateBugSelectors();
  //updateBugView();
} // end windowLoad()


/**
 * Called when Boogie is going to be unloaded
 */
function windowUnload() 
{
  // ...
} // end windowUnload() 

/* ----- // Main window - global events ----- */



/* ----- Update functions ----- */

function updateView() {
  if (viewIssuesBroadcaster.getAttribute("checked") == "true") {
    mainDeck.selectedIndex = 0;
    document.title = "Boogie - " + issuesButton.label;
  }
  if (viewProjectsBroadcaster.getAttribute("checked") == "true") {
    mainDeck.selectedIndex = 1;
    document.title = "Boogie - " + projectsButton.label;
  }
  if (viewDevelopersBroadcaster.getAttribute("checked") == "true") {
    mainDeck.selectedIndex = 2;
    document.title = "Boogie - " + developersButton.label;
  }
  if (viewNotesBroadcaster.getAttribute("checked") == "true") {
    mainDeck.selectedIndex = 3;
    document.title = "Boogie - " + notesButton.label;
  }
  if (viewReportsBroadcaster.getAttribute("checked") == "true") {
    mainDeck.selectedIndex = 4;
    document.title = "Boogie - " + notesButton.label;
  }
}

function updateCurrentProject() {
  newBugButton.disabled        = (boogieDb.getProjectsCount() == 0 || boogieDb.getDevelopersCount() == 0);
  newEnhacementButton.disabled = (boogieDb.getProjectsCount() == 0 || boogieDb.getDevelopersCount() == 0);
  projectMenulist.disabled     = (boogieDb.getProjectsCount() == 0);

  if (boogieDb.getProjectsCount() != 0) {
    var index = projectMenulist.selectedIndex;
    fillMenulist(projectMenulist, boogieDb.getProjects(), 1, false);
    if (index != -1 && index < boogieDb.getProjectsCount()) {
      projectMenulist.selectedIndex = index;
    } else {
      projectMenulist.selectedIndex = 0;
    }
  } else {
    projectMenulist.appendItem("(no project)", 0);
  }
}

function updateBugView() {
  var filteredBugs = boogieDb.getBugs();
  
  var idp = projectMenulist.value;
  if (idp != 0)
    filteredBugs = boogieDb.getBugs('idp', idp);
  
  var idt = typeMenulist.value;
  if (idt != 0)
    filteredBugs = boogieDb.getBugs('idt', idt);

  var idc = componentMenulist.value;
  if (idc != 0)
    filteredBugs = boogieDb.getBugs('idc', idc);

  var idd = developerMenulist.value;
  if (idd != 0)
    filteredBugs = boogieDb.getBugs('idd', idd);

  var ids = statusMenulist.value;
  if (ids != 0)
    filteredBugs = boogieDb.getBugs('ids', ids);

  var idr = resolutionMenulist.value;
  if (idr != 0)
    filteredBugs = boogieDb.getBugs('idr', idr);

  var idpr = priorityMenulist.value;
  if (idpr != 0)
    filteredBugs = boogieDb.getBugs('idpr', idpr);

  var idsv = severityMenulist.value;
  if (idsv != 0)
    filteredBugs = boogieDb.getBugs('idsv', idsv);

  var idv1 = versionMenulist.value;
  if (idv1 != 0)
    filteredBugs = boogieDb.getBugs('idv1', idv1);

  var idv2 = targetMenulist.value;
  if (idv2 != 0)
    filteredBugs = boogieDb.getBugs('idv2', idv2);

  bugView.projects = boogieDb.getProjects();
  bugView.types = boogieDb.getTypes();
  bugView.components = boogieDb.getComponents();
  bugView.developers = boogieDb.getDevelopers();
  bugView.statuses = boogieDb.getStatuses();
  bugView.resolutions = boogieDb.getResolutions();
  bugView.priorities = boogieDb.getPriorities();
  bugView.severities = boogieDb.getSeverities();
  bugView.versions = boogieDb.getVersions();
  
  bugView.bugs = filteredBugs;
}

function updateProjectsTree() {
  var projects = boogieDb.getProjects();
  projectsTree.treeView = new BoogieProjectsTreeViewPrototype(projects);
}

function updateComponentListbox() {
  var index = componentListbox.selectedIndex;

  removeListboxChilds(componentListbox);

  var componentsOrdered = components.selectItems(function(item) { return item.idp == projectsTree.value; })
    .orderedItems(orderByOrdering);
  for (var i = 0; i < componentsOrdered.items.length; i++) {
    componentListbox.appendItem(componentsOrdered.items[i].name,
      componentsOrdered.items[i].idc);
  }

  if (index < componentListbox.getRowCount())
    componentListbox.selectedIndex = index;
}

function updateVersionListbox() {
  var index = versionListbox.selectedIndex;

  removeListboxChilds(versionListbox);

  var versionsOrdered = versions.selectItems(function(item) { return item.idp == projectsTree.value; })
    .orderedItems(orderByOrdering);
  for (var i = 0; i < versionsOrdered.items.length; i++) {
    versionListbox.appendItem(versionsOrdered.items[i].name,
      versionsOrdered.items[i].idv);
  }

  if (index < versionListbox.getRowCount())
    versionListbox.selectedIndex = index;
}

/*function updateDevelopersTree() {
  var developers = boogieDb.getDevelopers();
  developersTree.view = new BoogieDevelopersTreeViewPrototype(developers);
}*/

/*function updateNotesTree() {
  var notes = boogieDb.getNotes();
  notesTree.view = new BoogieNotesTreeViewPrototype(notes);
}*/

/* ----- Helper functions ----- */

function editCurrentBug() {
  if (bugView.currentIndex != -1)
    window.openDialog("chrome://boogie/content/dialogs/issue-dialog.xul", "",
        "centerscreen,chrome,dialog,modal,dependent",
        { mode: "edit", idb : bugView.mBugs.items[bugView.currentIndex].idb });
  bugs.load();
  updateBugView();
}

/* ----- Main window - menu commands ----- */

function loadDatabaseCommand(mode) {
  var dlg = window.openDialog("chrome://boogie/content/preferences/preferences.xul",
                              "", "centerscreen,chrome,dialog,modal,dependent",
                              mode);
  if(dlg) dlg.focus();
  
  loadBugs();
  updateCurrentProject();
  updateBugView();
}

function fileExitCommand() {
  window.close();
}

function viewIssuesCommand() {
  viewIssuesBroadcaster.setAttribute("checked", "true");
  viewProjectsBroadcaster.setAttribute("checked", "false");
  viewDevelopersBroadcaster.setAttribute("checked", "false");
  viewNotesBroadcaster.setAttribute("checked", "false");
  viewReportsBroadcaster.setAttribute("checked", "false");
  updateView();
}

function viewProjectsCommand() {
  viewIssuesBroadcaster.setAttribute("checked", "false");
  viewProjectsBroadcaster.setAttribute("checked", "true");
  viewDevelopersBroadcaster.setAttribute("checked", "false");
  viewNotesBroadcaster.setAttribute("checked", "false");
  viewReportsBroadcaster.setAttribute("checked", "false");
  updateView();
}

function viewDevelopersCommand() {
  viewIssuesBroadcaster.setAttribute("checked", "false");
  viewProjectsBroadcaster.setAttribute("checked", "false");
  viewDevelopersBroadcaster.setAttribute("checked", "true");
  viewNotesBroadcaster.setAttribute("checked", "false");
  viewReportsBroadcaster.setAttribute("checked", "false");
  updateView();
}

function viewNotesCommand() {
  viewIssuesBroadcaster.setAttribute("checked", "false");
  viewProjectsBroadcaster.setAttribute("checked", "false");
  viewDevelopersBroadcaster.setAttribute("checked", "false");
  viewNotesBroadcaster.setAttribute("checked", "true");
  viewReportsBroadcaster.setAttribute("checked", "false");
  updateView();
}

function viewReportsCommand() {
  viewIssuesBroadcaster.setAttribute("checked", "false");
  viewProjectsBroadcaster.setAttribute("checked", "false");
  viewDevelopersBroadcaster.setAttribute("checked", "false");
  viewNotesBroadcaster.setAttribute("checked", "false");
  viewReportsBroadcaster.setAttribute("checked", "true");
  updateView();
}

function viewPreferencesCommand() {
  var dlg = window.openDialog("chrome://boogie/content/preferences/preferences.xul",
                              "", "centerscreen,chrome,dialog,modal,dependent",
                              "normal");
  if(dlg) dlg.focus();
}

function viewErrorConsoleCommand() {
  var win = window.open("chrome://global/content/console.xul",
                        "global:console",
                        "chrome,extrachrome,toolbar,resizable,centerscreen,all");
  if(win) win.focus();
}

function helpAboutCommand() {
  window.openDialog("chrome://boogie/content/about.xul", "",
    "centerscreen,chrome,dialog,modal,dependent");
}

/* ----- Main window - issues view ----- */

function newBugButtonClick() {
  if (!newBugButton.disabled) {
    window.openDialog("chrome://boogie/content/dialogs/issue-dialog.xul", "",
      "centerscreen,chrome,dialog,modal,dependent",
      { mode: "new", idp: projectMenulist.value, idt: IDT_BUG });
    bugs.load();
    updateBugView();
    projectsTreeSelect();
    componentListboxSelect();
    versionListboxSelect();
    developersTreeSelect();
  }
}

function newEnhacementButtonClick() {
  if (!newBugButton.disabled) {
    window.openDialog("chrome://boogie/content/dialogs/issue-dialog.xul", "",
      "centerscreen,chrome,dialog,modal,dependent",
      { mode: "new", idp: projectMenulist.value, idt: IDT_ENHACEMENT });
    bugs.load();
    updateBugView();
    projectsTreeSelect();
    componentListboxSelect();
    versionListboxSelect();
    developersTreeSelect();
  }
}

function bugViewKeyPress(event) {
  if (event.keyCode == 13)
    editCurrentBug();
}

function bugViewDblClick(event) {
  if (event.button == 0)
    editCurrentBug();
}

function projectMenulistCommand() {
  updateBugView();
}

function typeMenulistCommand() {
  updateBugView();
}

function componentMenulistCommand() {
  updateBugView();
}

function developerMenulistCommand() {
  updateBugView();
}

function statusMenulistCommand() {
  updateBugView();
}

function resolutionMenulistCommand() {
  updateBugView();
}

function priorityMenulistCommand() {
  updateBugView();
}

function severityMenulistCommand() {
  updateBugView();
}

function versionMenulistCommand() {
  updateBugView();
}

function targetMenulistCommand() {
  updateBugView();
}

/* ----- Main window - projects view ----- */

function projectsTreeSelect() {
  if (projectsTree.selectedIndex != -1) {
    var selectedBugs = bugs.selectItems(function(item) { return item.idp == projectsTree.value });
    editProjectButton.disabled = false;
    deleteProjectButton.disabled = selectedBugs.items.length > 0;
    //moveUpProjectButton.disabled = projectsTree.selectedIndex == 0;
    //moveDownProjectButton.disabled = projectsTree.selectedIndex == projectsTree.getRowCount() - 1;

    currentProjectHeader.setAttribute("value", projectsTree.selectedItem.label);
    //currentProjectHeader.style.color = "HighlightText";
    //currentProjectHeader.style.backgroundColor = "Highlight";

    newComponentButton.disabled = false;
    updateComponentListbox();
    componentListboxSelect(componentListbox);

    newVersionButton.disabled = false;
    updateVersionListbox();
    versionListboxSelect(versionListbox);
  } else {
    editProjectButton.disabled = true;
    deleteProjectButton.disabled = true;
    //moveUpProjectButton.disabled = true;
    //moveDownProjectButton.disabled = true;

    currentProjectHeader.setAttribute("value", "\u00a0");
    //currentProjectHeader.style.color = "InactiveCaptionText";
    //currentProjectHeader.style.backgroundColor = "InactiveCaption";

    componentListbox.disabled = true;
    newComponentButton.disabled = true;
    editComponentButton.disabled = true;
    deleteComponentButton.disabled = true;
    //moveUpComponentButton.disabled = true;
    //moveDownComponentButton.disabled = true;

    versionListbox.disabled = true;
    newVersionButton.disabled = true;
    editVersionButton.disabled = true;
    deleteVersionButton.disabled = true;
    //moveUpVersionButton.disabled = true;
    //moveDownVersionButton.disabled = true;
  }
}

function newProjectButtonClick() {
  var dlg = window.openDialog("chrome://boogie/content/dialogs/project-dialog.xul", 
                              "",
                              "centerscreen,chrome,dialog,modal,dependent", 
                              { mode: "new" });
  if(dlg) dlg.focus();
}

function editProjectButtonClick() {
  var dlg = window.openDialog("chrome://boogie/content/dialogs/project-dialog.xul", 
                              "",
                              "centerscreen,chrome,dialog,modal,dependent", 
                              { mode : "edit", idp : projectsTree.value });
}

function deleteProjectButtonClick() {
  if (!deleteProjectButton.disabled) {
    projects.deleteItems(function(item) { return item.idp == projectsTree.value; });
    components.deleteItems(function(item) { return item.idp == projectsTree.value; });
    versions.deleteItems(function(item) { return item.idp == projectsTree.value; });

    if (projectsTree.selectedIndex >= projects.items.length)
      projectsTree.selectedIndex--;

    projects.save();
    components.save();
    versions.save();
    updateProjectsTree();
    /* Next two are needed beacuse in the edge case, where the deleted project
       was the last, the onselect event on the projectsTree is not fired. */
    updateComponentListbox();
    updateVersionListbox();
  }
}

function componentListboxSelect() {
  if (componentListbox.selectedIndex != -1) {
    var selectedBugs = bugs.selectItems(function(item) { return item.idc == componentListbox.value });
    editComponentButton.disabled = false;
    deleteComponentButton.disabled = selectedBugs.items.length > 0;
    //moveUpComponentButton.disabled = componentListbox.selectedIndex == 0;
    //moveDownComponentButton.disabled = componentListbox.selectedIndex == componentListbox.getRowCount() - 1;
  } else {
    editComponentButton.disabled = true;
    deleteComponentButton.disabled = true;
    //moveUpComponentButton.disabled = true;
    //moveDownComponentButton.disabled = true;
  }
}

function newComponentButtonClick() {
  if (!newComponentButton.disabled) {
    window.openDialog("chrome://boogie/content/dialogs/component-dialog.xul", "",
      "centerscreen,chrome,dialog,modal,dependent", { mode: "new", idp: projectsTree.value });
    var n = components.items.length;
    components.load();
    updateComponentListbox();
    if (components.items.length > n)
      componentListbox.selectedIndex = componentListbox.getRowCount() - 1;
  }
}

function editComponentButtonClick() {
  window.openDialog("chrome://boogie/content/dialogs/component-dialog.xul", "",
    "centerscreen,chrome,dialog,modal,dependent", { mode: "edit", idc: componentListbox.value });
  components.load();
  updateComponentListbox();
}

function deleteComponentButtonClick() {
  if (!deleteComponentButton.disabled) {
    components.deleteItems(function(item) { return item.idc == componentListbox.value; });

    if (componentListbox.selectedIndex >= components.items.length)
      componentListbox.selectedIndex--;

    components.save();
    updateComponentListbox();
  }
}

function versionListboxSelect() {
  if (versionListbox.selectedIndex != -1) {
    var selectedBugs = bugs.selectItems(function(item) { return item.idv1 == versionListbox.value || item.idv2 == versionListbox.value; });
    editVersionButton.disabled = false;
    deleteVersionButton.disabled = selectedBugs.items.length > 0;
    //moveUpVersionButton.disabled = versionListbox.selectedIndex == 0;
    //moveDownVersionButton.disabled = versionListbox.selectedIndex == versionListbox.getRowCount() - 1;
  } else {
    editVersionButton.disabled = true;
    deleteVersionButton.disabled = true;
    //moveUpVersionButton.disabled = true;
    //moveDownVersionButton.disabled = true;
  }
}

function newVersionButtonClick() {
  if (!newVersionButton.disabled) {
    window.openDialog("chrome://boogie/content/dialogs/version-dialog.xul", "",
      "centerscreen,chrome,dialog,modal,dependent", { mode: "new", idp: projectsTree.value });
    var n = versions.items.length;
    versions.load();
    updateVersionListbox();
    if (versions.items.length > n)
      versionListbox.selectedIndex = versionListbox.getRowCount() - 1;
  }
}

function editVersionButtonClick() {
  window.openDialog("chrome://boogie/content/dialogs/version-dialog.xul", "",
    "centerscreen,chrome,dialog,modal,dependent", { mode: "edit", idv: versionListbox.value });
  versions.load();
  updateVersionListbox();
}

function deleteVersionButtonClick() {
  if (!deleteVersionButton.disabled) {
    versions.deleteItems(function(item) { return item.idv == versionListbox.value; });

    if (versionListbox.selectedIndex >= versions.items.length)
      versionListbox.selectedIndex--;

    versions.save();
    updateVersionListbox();
  }
}

function toggleIssuesTreeFilter(button_elm) {
  var filter_grid = document.getElementById("filter-groupbox-grid");
  
  filter_grid.collapsed = !filter_grid.collapsed;
  //button_elm.checked = !filter_grid.collapsed;
}

/* ----- Main window - developers view ----- */

function developersTreeSelect() {
  if (developersTree.selectedIndex != -1) {
    var selectedBugs = bugs.selectItems(function(item) { return item.idd == developersTree.value });
    editDeveloperButton.disabled = false;
    deleteDeveloperButton.disabled = selectedBugs.items.length > 0;
    //moveUpDeveloperButton.disabled = developersTree.selectedIndex == 0;
    //moveDownDeveloperButton.disabled = developersTree.selectedIndex == developersTree.getRowCount() - 1;
  } else {
    editDeveloperButton.disabled = true;
    deleteDeveloperButton.disabled = true;
    //moveUpDeveloperButton.disabled = true;
    //moveDownDeveloperButton.disabled = true;
  }
}

function newDeveloperButtonClick() {
  var dlg = window.openDialog("chrome://boogie/content/dialogs/developer-dialog.xul", 
                              "",
                              "centerscreen,chrome,dialog,modal,dependent", 
                              { mode: "new" });
  if(dlg) dlg.focus();
}

function editDeveloperButtonClick() {
  var dlg = window.openDialog("chrome://boogie/content/dialogs/developer-dialog.xul", 
                              "",
                              "centerscreen,chrome,dialog,modal,dependent", 
                              { mode : "edit", idd : developersTree.value });
}

function deleteDeveloperButtonClick() {
  if (!deleteDeveloperButton.disabled) {
    developers.deleteItems(function(item) { return item.idd == developersTree.value; });

    if (developersTree.selectedIndex >= developers.items.length)
      developersTree.selectedIndex--;
      
    developers.save();
    updateDevelopersTree();
  }
}

/* ----- Main window - notes view ----- */

function notesTreeSelect() {
  if (notesTree.selectedIndex != -1) {
    var selectedBugs = bugs.selectItems(function(item) { return item.idd == notesTree.value });
    editNoteButton.disabled = false;
    deleteNoteButton.disabled = false;
  } else {
    editNoteButton.disabled = true;
    deleteNoteButton.disabled = true;
  }
}

function newNoteButtonClick() 
{
  var dlg = window.openDialog("chrome://boogie/content/dialogs/note-dialog.xul", 
                              "",
                              "centerscreen,chrome,dialog,modal,dependent", 
                              { mode: "new" });
  if(dlg) dlg.focus();
}

function editNoteButtonClick() 
{
  var dlg = window.openDialog("chrome://boogie/content/dialogs/note-dialog.xul", 
                              "",
                              "centerscreen,chrome,dialog,modal,dependent", 
                              { mode : "edit", idn : notesTree.value });
}

function deleteNoteButtonClick() 
{
  if(!deleteNoteButton.disabled) 
    boogieDb.removeNote(notesTree.value);
}

