/**
 * Copyright 2008 CyberAgent FX,.inc. / http://www.gaikaex.net/
 *                KRAY inc.           / http://kray.jp/
 */
var Glossary = Class.create();
Glossary.prototype = Object.extend( new Object, {
  initialize : function(json, description_base, nodes, ignore_nodes, ignore_node_names, ignore_classes, ignore_words) {
    if (typeof nodes             == 'undefined') { nodes             = [document.body]; }
    if (typeof ignore_nodes      == 'undefined') { ignore_nodes      = []; }
    if (typeof ignore_node_names == 'undefined') { ignore_node_names = []; }
    if (typeof ignore_classes    == 'undefined') { ignore_classes    = []; }
    if (typeof ignore_words      == 'undefined') { ignore_words      = []; }
    nodes = $A([nodes]).flatten().map(function(value, index) {
      return $(value);
    });
    this.ignore_nodes = $A([ignore_nodes]).flatten().map(function(value, index) {
      return $(value);
    });
    this.ignore_node_names = $A([ignore_node_names]).flatten().map(function(value, index) {
      return value.toUpperCase();
    }).concat(['A', 'OPTION', 'TEXTAREA', 'SCRIPT', 'MAP', 'BASEFONT', 'BR', 'COL', 'COLGROUP', 'HR', 'IMG', 'INPUT', 'ISINDEX', 'OPTGROUP', 'OPTION', 'PARAM']);
    this.ignore_classes = $A([ignore_classes]).flatten().concat('ignore_glossary', 'disable_glossary');
    this.ignore_words   = $A([ignore_words]).flatten();
    this.description_base = description_base;
    this.text_nodes = [[], []];
    var ajax = new Ajax.Request(
      json, {
        method: 'get',
        onComplete: function(conn, result) {
          this.words = eval(conn.responseText);
          this.filter_text_nodes(nodes);
          this.anchor_to_text_nodes();
        }.bind(this),
        onException: function(conn, e) {}
      }
    );
  },

  NodeType: {
    ELEMENT:                1,
    ATTRIBUTE:              2,
    TEXT:                   3,
    CDATA_SECTION:          4,
    ENTITY_REFERENCE:       5,
    ENTITY:                 6,
    PROCESSING_INSTRUCTION: 7,
    COMMENT:                8,
    DOCUMENT:               9,
    DOCUMENT_TYPE:         10,
    DOCUMENT_FRAGMENT:     11,
    NOTATION:              12
  },

  RE_NOT_BLANK: /\S/,

  filter_text_nodes: function(nodes) {
    $A(nodes).flatten().each(function(node) {
      if (typeof node == 'undefined') { return; }
      this.filter_element(node);
    }.bind(this));
  },

  filter_element: function(root) {
    var has_enable_node = false;
    var nodes = root.childNodes;
    var count = nodes.length;
    for (var i = 0; i < count; i++) {
      var node = nodes[i];
      if (node.nodeType == this.NodeType.TEXT) {
        if (node.data.match(this.RE_NOT_BLANK) == null) { continue; }
        this.text_nodes[0].push(node);
      } else if (node.nodeType == this.NodeType.ELEMENT) {
        if (this.ignore_nodes.include(node) || this.ignore_node_names.include(node.nodeName)) { continue; }
        var has_ignore_class = false;
        var class_names = $A(Element.classNames(node));
        for (var j = 0; j < class_names.length; j++) {
          if (this.ignore_classes.include(class_names[j])) {
            has_ignore_class = true;
            break;
          }
        }
        if (has_ignore_class) { continue; }
        this.filter_element(node);
      }
    }
  },

  anchor_to_text_nodes: function() {
    this.words.each(function(word) {
      if (this.ignore_words.include(word['w'])) { return; }
      this.text_nodes[1].clear();
      var nodes = this.text_nodes[0];
      var count = nodes.length;
      for (var i = 0; i < count; i++) {
        var node = nodes[i];
        this.text_nodes[1].push(this.anchor_to_word(word, node));
      };
      this.text_nodes[0] = this.text_nodes[1].flatten();
    }.bind(this));
  },

  anchor_to_word: function(word, node) {
    var text = node.data;
    var anchored_nodes = [];
    var parent = node.parentNode;
    var key = word['w'];
    if (text.indexOf(key) == -1) { return node; }
    var text_nodes = [];
    var snippets = text.split(key);
    var anchor;
    for (var i = 0; i < snippets.length; i++) {
      if (i > 0) {
        anchor = document.createElement('A');
        anchor.href = this.description_base + word['id'];
        anchor.innerHTML = key;
        Element.addClassName(anchor, 'glossary');
        Event.observe(anchor, 'mouseover', function() { Tip('<span class="tooltip_title">' + word['w'] + '</span><br /><br /><span style="tooltip_body">' + word['d'] + '</span>', ABOVE, true, STICKY, true, DURATION, 3000, CLICKCLOSE, true, WIDTH, 240, OFFSETY, 15, BORDERCOLOR, '#808080', BGCOLOR, '#f0f0f0', FONTCOLOR, '#666666'); });
        Event.observe(anchor, 'mouseout',  function() { UnTip(); });
        anchored_nodes.push(anchor);
      }
      var text_node = document.createTextNode(snippets[i]);
      text_nodes.push(text_node);
      anchored_nodes.push(text_node);
    }
    var next_sibling = node.nextSibling;
    parent.removeChild(node);
    if (next_sibling) {
      anchored_nodes.each(function(node) {
        parent.insertBefore(node, next_sibling);
      });
    } else {
      anchored_nodes.each(function(node) {
        parent.appendChild(node);
      });
    }
    return text_nodes;
  }
} );
