var oraTagCloudDefaultOptions = {
     cloudClass: "tagcloud",
     titleClass: "title",
     contentClass: "content",
     linkClass: "link",
     textClass: "text",
};
var oraTagCloud = function(tagCloudInfo, options) {
    this.options = MochiKit.Base.clone(oraTagCloudDefaultOptions);
    if(MochiKit.DOM.$(options) && MochiKit.DOM.$(options).parentNode) {
       this.options.container = MochiKit.DOM.$(options);
    } else {
       if(typeof(options) == "string") {
          throw new Error("could not find element " + options);
       } else {
          MochiKit.Base.update(this.options, options);
          if(this.options.container) {
             this.options.container = MochiKit.DOM.$(this.options.container);
          }
       }
    }
    if(typeof(tagCloudInfo) == "string") {
       var d = MochiKit.Async.loadJSONDoc(tagCloudInfo);
       d.addCallbacks(MochiKit.Base.bind(function(obj) {
           this.jsonObj = obj;
           this.prepareInfo();
           this.makeCloudDiv();

           if(this.options.container) {
               MochiKit.DOM.replaceChildNodes(this.options.container, this.div);
           }
           MochiKit.Signal.signal(this, 'ready', this);
       }, this), MochiKit.Base.bind(function(e) {
             MochiKit.Signal.signal(this, 'error', e);
       }, this));
    } else if(typeof(tagCloudInfo) == "object") {
        this.jsonObj = tagCloudInfo;
        this.prepareInfo();
        this.makeCloudDiv();
       if(this.options.container) {
           MochiKit.DOM.appendChildNodes(this.options.container, this.div);
       }
    }
};

oraTagCloud.prototype.prepareInfo = function() {
    for(var i = 1; i <= 7; i++) {
        var span = MochiKit.DOM.SPAN({ class: "size" + i });
        var div = MochiKit.DOM.DIV({ class: this.options.cloudClass },
            MochiKit.DOM.DIV({ class: this.options.contentClass }, span));
        this["useDefaultSize" + i] = false;
        if(MochiKit.DOM.computedStyle(span, "font-size") == 
                  MochiKit.DOM.computedStyle(MochiKit.DOM.SPAN(), "font-size")) {
            this["useDefaultSize" + i] = true;
        }
    }

    this.sizes = MochiKit.Base.map(function(a) { return a.size }, this.jsonObj.tags);
    this.sizes.sort(function(a,b) { return b-a; });

    /* shouldn't be necessary when web service gives correct sizes */
    this.max = this.sizes[0];
    this.min = this.sizes[this.sizes.length-1];
    this.factor = 7*this.min/this.max;

    for(var i = 0; i < this.jsonObj.tags.length; i++) {
       var str = "" + this.jsonObj.tags[i].size;
       this.jsonObj.tags[i].size = Math.round(this.factor*this.jsonObj.tags[i].size/this.min);
    }
};

oraTagCloud.prototype.getCloud = function(obj) {
   if(obj && obj.asHTML) {
      return MochiKit.DOM.DIV({}, this.div).innerHTML;
   }
   return this.div;
};

oraTagCloud.prototype.makeCloudDiv = function() {
     var c = this.options.cloudClass;
     var titlec = this.options.titleClass;
     var contentc = this.options.contentClass;
     var linkc = this.options.linkClass;
     var textc = this.options.textClass;


     var div = MochiKit.DOM.DIV({ class: c },
        MochiKit.DOM.DIV({class: titlec}, this.options.title || this.jsonObj.title),
        MochiKit.DOM.DIV({ class: contentc }, MochiKit.Base.map(MochiKit.Base.bind(function(tag) {
           var span_attr = {};
           if(this["useDefaultSize" + tag.size]) {
               span_attr.style = "font-size: " + (10+(21-3*tag.size)); 
           } else {
               span_attr.class = "size" + tag.size;
           }
           var tag_span = MochiKit.DOM.SPAN(span_attr);
           
           var tagc = textc;
           var text_in = tag_span;
           if(tag.link) {
               tagc = linkc;
               text_in = MochiKit.DOM.A({ href: tag.link });
               MochiKit.DOM.appendChildNodes(tag_span, text_in);
           }
           text_in.innerHTML = tag.word;
           MochiKit.DOM.addElementClass(tag_span, tagc);

           return [ tag_span, " "];
        }, this), this.tagsToDisplay()))
     );

     this.div = div;
};

oraTagCloud.prototype.tagsToDisplay = function() {
   var tags = [];
   if(this.options.top && this.options.top < this.jsonObj.tags.length) {
      var i = 0;
      while(tags.length < this.options.top && i < this.jsonObj.tags.length) {
         if(this.jsonObj.tags[i].size <= this.sizes[this.options.top-1]) {
             tags.push(this.jsonObj.tags[i]);
         }
         i++;
      }
   } else {
      tags = MochiKit.Base.clone(this.jsonObj.tags);
   }
   if(this.options.orderby == "alpha") {
      tags.sort(function(a, b) { return MochiKit.Base.compare(a.word, b.word) });
   } else if(this.options.orderby == "size") {
      tags.sort(function(a, b) { return b.size-a.size });
   } else if(this.options.orderby == "shuffle") {
      oraTagCloud.shuffle(tags);
   }
   return tags;
}; 

oraTagCloud.shuffle = function(list) {
   var r;
   for(var i = 0; i < list.length; i++) {
      r = Math.floor(Math.random()*list.length)
      var tmp = list[r];
      list[r] = list[i];
      list[i] = tmp;
   }
   return list;
};

