// copyright (c) 2006-2008 Franz Inc, Oakland, CA - All rights reserved.
//
// The software, data and information contained herein are proprietary
// to, and comprise valuable trade secrets of, Franz, Inc.  They are
// given in confidence by Franz, Inc. pursuant to a written license
// agreement, and may be stored and used only in accordance with the terms
// of such license.
//
// Restricted Rights Legend
// ------------------------
// Use, duplication, and disclosure of the software, data and information
// contained herein by any agency, department or entity of the U.S.
// Government are subject to restrictions of Restricted Rights for
// Commercial Software developed at private expense as specified in
// DOD FAR Supplement 52.227-7013 (c) (1) (ii), as applicable.

// Functionality related to modifying the store.

function deleteNamespace(abbrev) {
  showDialog("Delete namespace '" + abbrev + "'?", doDelete, null);
  function doDelete() {
    postJSON("db/namespace/remove", [abbrev], success, failure);
    function success(data) {
      setDBInfo(data);
      refresh();
      showMessage("Namespace deleted.", 1.5, false);
    }
    function failure(message) {
      failMessage("Deleting namespace", message);
    }
  }
}

function namespaceDialog() {
  if ($("namespace-abbrev")) return;
  var close = customDialog("store/namespace", {ok: addNamespace, cancel: function(){close();}}, false, false);

  function addNamespace(abbrev, uri) {
    postJSON("db/namespace/add", [abbrev, uri], success, failure);
    var loading = $("namespace-loading");
    loading.style.visibility = "";

    function success(data) {
      setDBInfo(data);
      close();
      refresh();
      showMessage("Namespace added.", 1.5, false);
    }
    function failure(message) {
      loading.style.visibility = "hidden";
      failMessage("Adding namespace", message);
    }
  }
}

function editStoreText() {
  var container = $("db-blurb");
  function editField(text) {
    Mold.cast(container, template("store/editblurb"), {
      text: text,
      cancel: function() {Mold.cast(container, template("store/blurb"), dbInfo.blurb);},
      ok: saveBlurb
    });
  }
  editField(dbInfo.blurb);

  function saveBlurb(text) {
    postJSON("db/setinfo", [dbInfo.name, text], success, failure);
    Mold.cast(container, template("store/saving"));

    function success(data) {
      setDBInfo(data);
      refresh();
      showMessage("Store text saved.", 1.5, false);
    }
    function failure(message) {
      editField(text);
      failMessage("Saving text", message);
    }
  }
}

function changeStoreName() {
  showPrompt("New store name", saveName, null, false, false);
  function saveName(name) {
    activityPost("db/setinfo", [name, dbInfo.blurb], "Saving store name", setDBInfo);
  }
}

function deleteNotable(node) {
  postJSON("db/notable/remove", [node], success, failure);
  function success(data) {
    setDBInfo(data);
    refresh();
    showMessage("Notable node deleted.", 1.5, false);
  }
  function failure(message) {
    failMessage("Deleting node", message);
  }
}

function addNotable() {
  if ($("notable-loading")) return;
  var close = customDialog("store/addnotable", {ok: add, cancel: function(){close();}}, false, false);

  function add(node, caption) {
    var string = NameSpaces.restore(node);
    if (string == null)
      showMessage("'" + node + "' is not a valid node", true, true);
    else {
      var loading = $("notable-loading");
      loading.style.visibility = "";
      function success(data) {
        close();
        setDBInfo(data);
        refresh();
      }
      function failure(message) {
        loading.style.visibility = "hidden";
        failMessage("Adding node", message);
      }
      postJSON("db/notable/add", [string, caption], success, failure);
    }
  }
}

function setDBReasoning(on) {
  postJSON("db/setreasoning", [on], success, failure);
  function success(data) {
    setDBInfo(data);
    refresh();
  }
  function failure(message) {
    failMessage("Changing reasoning", message);
  }
}

function deleteDBQuery(name) {
  postJSON("db/query/remove", [name], success, failure);
  function success(data) {
    setDBInfo(data);
    refresh();
  }
  function failure(message) {
    failMessage("Removing query", message);
  }
}

function addDBQuery(query) {
  activityPost("db/query/add", [query.type, query.title, query.text], "Storing query", function(data) {
    setDBInfo(data);
    goTo("query/db/" + query.title);
  });
}

function indexTriples(all) {
  activityPost("store/index", [all], "Indexing triples", function() {
    dbInfo.indexCoverage = 1;
  });
}

function addTripleDialog(slot, part) {
  if ($("new-triple-loading")) return;

  // Used to fill in a default value in the form.
  var data = {ok: addTriple, cancel: function(){close();}};
  forEach(["s", "p", "o"], function(type) {
    data[type] = slot == type ? part.string : "";
  });
  var close = customDialog("store/newtriple", data, false, false);

  function addTriple(subject, predicate, object, graph) {
    // Expand abbreviated namespaces in a node. Note that the graph
    // node may be null.
    function restore(str, graph) {
      if (graph && str == null) return null;
      var full = NameSpaces.restore(str);
      if (!full) showMessage("'" + str + "' is not a valid part.");
      return full != null && full;
    }
    if (!((s = restore(subject)) && (p = restore(predicate)) && (o = restore(object)) && (g = restore(graph, true)) !== false))
      return;

    postJSON("triple/add", [s, p, o, g], success, failure);
    var loading = $("new-triple-loading");
    loading.style.visibility = "";
    
    function success(data) {
      close();
      setDBInfo(data);
      refresh();
      showMessage("Triple successfully added.", 2, false);
    }
    function failure(message) {
      loading.style.visibility = "hidden";
      failMessage("Adding triple", message);
    }
  }
}

function deleteTriple(triple) {
  activityPost("triple/delete", [triple[0], triple[1], triple[2], triple[3] || null], "Deleting triple", function(deleted) {
    if (deleted) dbInfo.triples--;
  });
}

// Importing a file requires an upload, and hence a form post. The
// system uses an iframe to post to, and the store/importfile service
// returns a small html page which calls the ok or fail function on
// its frame node.
function uploadDialog() {
  if ($("file-uploading")) return;
  var close = customDialog("store/importfile", {start: startUpload, cancel: function(){close();}}, false, false);
  var submitting = false;

  function startUpload($event) {
    if (submitting) {$event.stop(); return;}

    var frame = $("triple-file-upload"), loading = $("file-uploading");
    loading.style.visibility = "";
    submitting = true;

    frame.ok = function(data) {
      close();
      setDBInfo(data);
      refresh();
      showMessage("Triples successfully imported.", 2, false);
    };
    frame.fail = function(message) {
      submitting = false;
      loading.style.visibility = "hidden";
      failMessage("Import", message);
    }
  }
}

function newTextIndex() {
  showPrompt("Predicate to index:", saveIndex, null, false, false);
  function saveIndex(name) {
    var full = partFromUntrusted(name);
    if (!full || !full.url) {
      showMessage("'" + name + "' is not a valid text-indexing predicate. Predicate must be an URI in <http://something.or/other> form.",
                  true, true);
      return;
    }
    activityPost("freetext/index/add", [full.string], "Adding text index", function() {
      dbInfo.freetext.push(full.string);
    });
  }
}

function calaisDialog() {
  if ($("calais-loading")) return;
  var close = customDialog("store/calais", {ok: runCalais, cancel: function(){close();}}, false, false);

  function runCalais(url) {
    postJSON("store/opencalais", [url], success, failure);
    var loading = $("calais-loading");
    loading.style.visibility = "";
    function success(data) {
      setDBInfo(data);
      refresh();
      showMessage("OpenCalais results imported.", 1.5, false);
    }
    function failure(message) {
      loading.style.visibility = "hidden";
      failMessage("Entity-extraction", message);
    }
  }
}