/* Javascript Workspace Client Evaluator
 *
 * Copyright (c) 2007 Takashi Yammaiya
 *
 * 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 THE AUTHORS OR COPYRIGHT HOLDERS
 * 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.
 */

/* event handler for short cut key */
function onShortCutKey (evt)
{
  evt = (evt) ? evt : window.event;
  if (!evt) return;
  var charCode = (evt.charCode) ? evt.charCode : evt.keyCode;
  if (!(evt.altKey || evt.ctrlKey || evt.metaKey)) {
    return true;
  }
  if (charCode == 68) {
    doIt();
  } else if (charCode == 80) {
    printIt();
  } else {
    return true;
  }
  if (evt.preventDefault) {
    evt.preventDefault();
    evt.stopPropagation();
  } else {
    evt.returnValue = false;
    evt.cancelBubble = true;
  }
  return false;
}

/* show current selection (for debugging) */
function selectIt() {
  var editor = workspace;
  result = getCaretSelection(editor);
  alert(result.start + ':' + result.end);
}

function printIt() {
  var result =  evalSelection();
  var editor = result.source.editor;
  var end = result.source.end;
  var head = editor.value.substring(0, end);
  var tail = editor.value.substring(end);
  editor.value = head + result.result + tail;
  setCaretSelection(editor, end, (head + result.result).length);
}

function doIt() {
  var result = evalSelection();
  result.source.editor.focus();
}

/* Get selection of textarea */
function getCaretSelection(field) {
    field.focus();
    var result = {start: 0, end: 0};
    // IE support based on http://groups.drupal.org/node/1210
    if(typeof workspace.selectionEnd == "undefined") {
        var range = document.selection.createRange();
        var rangeCopy = range.duplicate();
        rangeCopy.moveToElementText(field);
        rangeCopy.setEndPoint( 'EndToEnd', range );
        result.start = rangeCopy.text.length - range.text.length;
        result.end = result.start + range.text.length;
    } else {
        result.start = field.selectionStart;
        result.end = field.selectionEnd;
    }
    return result;
}

/* Set selection of textarea */
function setCaretSelection(field, start, end) {
    field.focus();
    // IE
    if(typeof workspace.selectionEnd == "undefined") {
        var range = document.selection.createRange();
        range.collapse(true);
        // CRLF conversion (bad sense though...)
        var length = end - start;
        var start0 = start -
            (field.value.substring(0, start).split("\n").length - 1);
        var length0 = length -
            (field.value.substring(start0, start0 + length).split("\n").length - 1);
        range.moveStart("character", start0);
        range.moveEnd("character", length0);
        range.select();
    } else {
        field.selectionStart = start;
        field.selectionEnd = end;
    }
}

/* Get expression from textarea */
function getSource() {
  var editor = workspace;
  var selection = getCaretSelection(editor);
  var start = selection.start;
  var end = selection.end;
  var text = editor.value.substring(start, end);
  if (start == end) {
    var alltext = editor.value;
    var index = 0;
    start = 0;
    while (true) {
      start = index;
      index = alltext.indexOf("\n", index);
      if (index >= end || index < 0) {
        break;
      }
      index = index + 1;
    }
    end = index < 0 ? alltext.length : index;
    text = alltext.substring(start, end);
    var selection = setCaretSelection(editor, start, end);
  }

  var source = {
    editor: editor,
    start: start,
    end: end,
    text: text
  };
  return source;
}

function evalSelection() {
  var source = getSource();
  var result;
  result = eval(source.text);
  
  resultObject = {
    source: source,
    result: result
  };
  return resultObject;
}

/* Utility APIs */

/* initialize */
window.onload = function () {
  /* window.workspace : reference to the editor */
  workspace = document.getElementById('editor');
  workspace.onkeydown = onShortCutKey;
}

/* window.show() : Append some text after the editor */
function show(object) {
  workspace.value = workspace.value + object;
}

/* window.dump() : dump all properties */
function dump(object) {
    var i;
    var result = "";
    for (i in object) {
        var value;
        try {value = object[i]} catch (e) {e};
        result = result + i + " = " + value + "\n";
    }
    return result;
}
