Editor.Selection = Class.create();
Editor.Selection._focusedImage = false;
Editor.Selection.prototype = {

  initialize: function(w) {
    this._window   = w;
    this._document = w.document;
    this.getSelection();
  },
  
  inspect: function() {
    return "selection: "  + this.selection + "\n" + 
           "range: "      + this.range + "\n" + 
           "text: "       + this.text + "\n" + 
           "htmlString: " + this.htmlString + "\n" + 
           "bookmark: "   + this.bookmark + "\n" +
           "ancestor: "   + this.commonAncestor() + "\n"
  },

  isEmpty: function() {
    if (Editor.hasGetSelection) {
      return this._window.getSelection().rangeCount == 0;
    } else {
      return this._document.selection.type == "None";
    }    
  },

  getSelection: function() {
    if (!this._document || !this._window) { return false; }
    if (Editor.Selection._focusedImage) { this.selectNode(Editor.Selection._focusedImage); }
    if (Editor.hasGetSelection) {
      this.bookmark   = false;
      this.selection  = this._window.getSelection();
      if (this.selection.rangeCount > 0) {
        this.range      = this.selection.getRangeAt(0);
        this.text       = this.range.toString();
        this.htmlString = this.getHtmlString(this.range.cloneContents());
      } else {
        this.range      = false;
        this.text       = false;
        this.htmlString = false;
      }
    } else {
      this.selection  = this._document.selection;
      this.range      = this.selection.createRange();
      this.text       = this.range.text;
      this.htmlString = this.range.htmlText;
      this.bookmark   = this.range.getBookmark();
    }
  },

  setSelection: function(options) {
    this.clearSelection();
    if (options.nodeType) {
      this.selectNode(options);
    } else {
      this.selectWithOffsets(options);
    }
    this.getSelection();
  },

  selectNode: function(node) {
    if (Editor.hasGetSelection) {
      var r = this._document.createRange();
      r.selectNode(node);
      this._window.getSelection().addRange(r);
    } else {
      var b = this._document.getElementsByTagName("body")[0];
      var r = b.createTextRange();
      r.collapse();
      r.moveToElementText(node);
      r.select();
    }
  },

  selectWithOffsets: function(options) {
    options.end         = options.end         || options.start;
    options.startOffset = options.startOffset || 0;
    options.endOffset   = options.endOffset   || options.startOffset;

    if (Editor.hasGetSelection) {
      var r = this._document.createRange();
      // If we just want text we have to descend into the node
      if (options.start == options.end && options.start.firstChild) {
        options.start = options.end = options.start.firstChild;
      }
      r.setStart(options.start, options.startOffset);
      r.setEnd(options.end, options.endOffset);
      this._window.getSelection().removeAllRanges();
      this._window.getSelection().addRange(r);
    } else {
      var b = this._document.getElementsByTagName("body")[0];

      var startRange = b.createTextRange();
      startRange.moveToElementText(options.start);
      startRange.collapse();
      startRange.moveStart("character", options.startOffset);

      var endRange = b.createTextRange();
      endRange.moveToElementText(options.end);
      endRange.collapse();
      endRange.moveStart("character", options.endOffset);

      startRange.setEndPoint("StartToEnd", endRange);
      startRange.select();
    }
  },

  clearSelection: function() {
    if (Editor.hasGetSelection) {
      this._window.getSelection().removeAllRanges();
    } else {
      this._document.selection.empty();
    }
  },

  getHtmlString: function(nodes) {
    var temp = this._document.createElement("span");
    temp.appendChild(nodes);
    return temp.innerHTML;
  },

  commonAncestor: function() {
    return this.range.parentElement ? 
      this.range.parentElement() : 
      this.range.commonAncestorContainer;
  },

  reset: function() {
    if (!this.bookmark) { return false }
    //this.range.moveToBookmark(this.bookmark);
    this.range.select();
  },

  updateText: function(text) {
    if (Editor.hasGetSelection) {
      this.selection.removeAllRanges();
      this.range.deleteContents();
      var text = this._document.createTextNode(text);
      this.range.insertNode(text);
      this.range.selectNode(text);
      this.selection.addRange(this.range);
    } else {
      this.range.pasteHTML(text);
      this.range.expand("textedit");
      this.range.findText(text);
      this.range.select();
    }
  }
}

if (!$s) {
  var $s = function(w) {
    w = w || (Editor.current ? Editor.current.iframe.window() : window);
    return new Editor.Selection(w);
  }
}
