function Hot() {

    this.hotUrl = "/GetHotlist";
    this.fetchInterval = 3000;
    this.transitionInterval = 500;
    this.idleInterval = 5000;
    this.totalRows = -1;
    this.rowsPerPage = 20;
    this.sortBy = 'time';
    this.currPage = -1;
    this.lastPage = 0;
    this.currRows = null;
    this.targetRows = null;
    this.addRow = null;
    this.delRow = null;
    this.nextRowId = 1;
    this.tidData = -1;
    this.tidTransition = -1;
    this.tidIdle = -1;
    this.idle = true;
    this.ctx = 0;
    this.currState = null;
    this.nextState = null;
    this.source = 'All';
    this.category = 'All';
    this.isHome = false;

    this.getHotTopics = function() {
        var sort = (this.sortBy == "rank" ? 0 : 1);
        $('#topics_box h2').text(this.category == 'All' ? 'Hot Topics In Wowd' : 'Hot Topics In ' + this.category)
            .attr('title', 'This is a tag cloud of the hot topics contained in the Hot List pages on the left');
        $.getJSONExt('/GetHotTopics', {t : sort, category: this.category, type: 'h'}, function(data) {
            hot.showHotTopics(data);
        });
    }

    this.showHotTopics = function(data) {
        var container = $('#topics_cloud');
        var topics = data.topics;
        var content = '';
        if (topics.length == 0) {
            content = '<span>There are no Hot Topics available for this search.</span>';
        } else {
            var terms = [], v, s, values = [];
            for (t in topics) {
                v = parseFloat(topics[t].weight);
                s = topics[t].topic;
                terms.push( {
                    topic : s,
                    value : v
                });
                values.push(v);
            }
            terms = terms.sort(function(f, s) {
                if (f.topic < s.topic)
                    return -1;
                if (f.topic == s.topic)
                    return 0;
                return 1;
            });

            values = values.sort();
            var min = values[0], max = values[values.length - 1];

            var add = (min < 0 ? Math.abs(min) : 0);
            max = (max + add + 1.1);

            min = 999999999999, max = -1;
            for (t in terms) {
                terms[t].value = (add + terms[t].value + 1.1) + 1;
                if(terms[t].value < min)
                    min = terms[t].value;
                if(terms[t].value > max)
                    max = terms[t].value;
            }

            var nmax = 0, nmin = 1;
            for (t in terms) {
                terms[t].value = terms[t].value / (max+min);
                if(terms[t].value < nmin)
                    nmin = terms[t].value;
                if(terms[t].value > nmax)
                    nmax = terms[t].value;
            }

            min = nmin;
            max = nmax;
            var id = 0;
            for (t in terms) {
                var topic = terms[t].topic, weight = terms[t].value, fontSize = this
                .getFontSize(min, max, weight), color = this.getColor(min, max,
                    weight);
                content += 
                    '<span id="ht' + id + '" class="cloud_topic_item" style="font-size:' + fontSize + 'px; color:' + color + ';" onmouseover="hot.showHidePlus(' + id + ', true)" onmouseout="hot.showHidePlus(' + id + ', false)" onClick="visitPage(\'' + topic + '\',\'tag\')">' +
                        this.generateSearchLink(topic, id) +
                        this.generateSearchLink2(topic, id) +
                    '</span>';
                id++;
            }
        }
        $("#topics_info").fadeOut('slow', function(){container.hide().html(content).fadeIn('slow')});
    }

    this.getFontSize = function(min, max, val) {
        var minFontSize = 10, maxFontSize = 18;
        var unit = 1 / (max - min);
        var diff;
        if((max - min) <= 1)
            diff = min * unit;
        else
            diff = min / unit;
        if (min == max)
            return minFontSize + (maxFontSize - minFontSize) / 2;
        if(val == min)
            return minFontSize;
        if(val == max)
            return maxFontSize;
        return minFontSize + (((val*unit) - diff) * (maxFontSize - minFontSize));
    }

    this.getColor = function(min, max, val) {
        return 'black';
    }

    this.showHidePlus = function(id, showHide) {
        //$("#ht" + id + " a").eq(1).css('color', showHide ? "#fc8a00" : "#fff");
    }

    this.generateSearchLink = function(topic, id) {
        return '<a href="index.jsp?search&query=' + escape(topic) + '&htq=' + escape(topic) + '&sortby=' + this.sortBy + '&source=' + this.source + '&category=' + this.category + '">' + topic + '</a>';
    }

    this.generateSearchLink2 = function(topic, id) {
        return '<a href="index.jsp?search&query=' + escape(topic) + '&htq=' + escape(topic) + '&sortby=' + this.sortBy + '&source=' + this.source + '&category=' + this.category + '" style="color:#fff;padding-left:2px;" title="Add this term to current search query">+</a>';
    }

    this.getTotalRows = function() {
        $.getJSONExt(this.hotUrl, {
            getTotalRows: "",
            category: this.category
        }, function(data) {
            if (data.totalRows) {
                hot.currPage = 1;
                hot.totalRows = data.totalRows;
                hot.fetchData();
            }
        }, function() {
            hot.tidData = setTimeout("hot.getTotalRows()", hot.fetchInterval)
        });
    }

    this.fetchData = function() {
        var start = (this.currPage-1) * this.rowsPerPage;
        if (start < 0)
            start = 0;

        var args = {
            getRows: true,
            start: start,
            count: this.rowsPerPage,
            sortby: this.sortBy,
            source : this.source,
            category: this.category
        };

        if (this.ctx != 0)
            args['ctx'] = this.ctx;

        $.getJSONExt(this.hotUrl, args, function(data) {
            if (hot.nextState == null)
                hot.currState = data.oldst;
            else
                hot.currState = hot.nextState;
            hot.nextState = data.newst;
            if (data.ctx)
                hot.ctx = data.ctx;

            if(!hot.currState)
            	hot.currState = [];
            
            if (hot.totalRows != hot.currState.length) {
                hot.currPage = 1;
                hot.totalRows = hot.currState.length;
            }

            for (var i = 0; i < data.newst.length; i++)
                data.newst[i].ord = i+1;

            var rows = data.newst.slice(
                (hot.currPage-1) * hot.rowsPerPage,
                hot.currPage * hot.rowsPerPage);
            if (hot.nextState.length > 0)
                $("#hot_running").hide();
            hot.renderRows(rows);
        }, function() {
            hot.tidData = setTimeout("hot.fetchData()", hot.fetchInterval)
        });
    }

    this.fetchPage = function() {
        $("#hot_results div.table_row").remove();
        clearTimeout(this.tidData);
        clearTimeout(this.tidTransition);
        this.currRows = new Array();
        this.targetRows = null;
        this.fetchData();
    }

    this.renderRowContent = function(row) {
        if (!row.id)
            row.id = this.nextRowId++;

        var title = row.showTitle;
        var tags = '';
        for (var i in row.tags) {
            var tagTitle = '';
            if (row.tags[i].code.endsWith('11')) {
                tagTitle = 'Show only items at site \'' + row.tags[i].show + '\'';
                tags += '<a href="index.jsp?search&query=&sortby=time&category=' + this.category + '&tags=' + escape(row.tags[i].show) + '|' + escape(row.tags[i].code) + '" ' +
                    'title="'  + tagTitle + '">' + row.tags[i].show + '</a>&nbsp;';
            } else if (row.tags[i].code.endsWith('22')) {
                var name = MapTagToCategory(row.tags[i].show);
                if (name != this.category) {
                    tagTitle = 'Show only items in category \'' + row.tags[i].show + '\'';
                    if (name != "")
                        tags += '<a href="javascript:;" onclick="wowd.goToCategory(\'' + MapTagToCategory(row.tags[i].show) + '\')" ' +
                            'title="'  + tagTitle + '">' + row.tags[i].show + '</a>&nbsp;';
                    else
                        tags += '<a href="index.jsp?search&query=&sortby=time&category=' + this.category + '&tags=' + escape(row.tags[i].show) + '|' + escape(row.tags[i].code) + '" ' +
                            'title="'  + tagTitle + '">' + row.tags[i].show + '</a>&nbsp;';
                }
            } else {
                tagTitle = 'Show only items with tag \'' + tags[i].show + '\'';
                tags += '<a href="index.jsp?search&query=&sortby=time&category=' + this.category + '&tags=' + escape(row.tags[i].show) + '|' + escape(row.tags[i].code) + '" ' +
                    'title="'  + tagTitle + '">' + row.tags[i].show + '</a>&nbsp;';
            }
        }

        var subject = escape('Here\'s something I found via Wowd');
        var body = escape('\n' + row.url + '\n\nDiscovered via Wowd (www.wowd.com)');
        var content =
            '<table width="100%" cellpadding="0" cellspacing="0"><tr>' +
            '<td valign="top" align="center" class="rank">' + Math.floor(row.ord + ((this.currPage-1) * this.rowsPerPage)) + '</td>' +
            '<td>&nbsp;</td>' +
            '<td align="left">' +
                '<div class="title"><a href="' + row.url + '" name="' + row.extID + '" target="_blank" title="' + row.url + '" onClick="visitPage(\'' + row.url + '\',\'hot\');">' + title + '</a></div>' +
                '<div class="snippet">' + row.abs + '</div>' +
                '<div>' +
                    '<span class="timestamp" title="Last viewed: ' + row.lastViewed + ', Last indexed: ' + row.timestamp + '">' + row.lastViewed + '</span>' +
                    '&nbsp;&nbsp;&nbsp;' +
                    '<span class="actions">' +
                        '<a href="mailto:?subject=' + subject + '&body=' + body + '"><img src="gfx/email.gif" title="Send to a friend" alt="Send to a friend" height="16" width="16"></a>' +
                        '<a href="javascript:;" onclick="ShowModal(\'#modal_sharing_win\', \'#modal_sharing\')"><img src="gfx/twitter-action.gif" title="Share this via Twitter" alt="Share this via Twitter" width="16" height="16" /></a>' +
                        '<a href="http://www.facebook.com/sharer.php?u=' + escape(row.url) + '&t=' + escape(row.title) + '" target="_blank"><img src="gfx/facebook-action.gif" title="Share this via Facebook" alt="Share this via Facebook" width="16" height="16" /></a>' +
                        '<a href="javascript:;" onclick="ShowModal(\'#modal_spam_win\', \'#modal_spam\')" ><img src="gfx/thumb_down.gif" title="Report as Inappropriate" alt="Report as Inappropriate" height="16" width="16"></a>' +
                    '</span>' +
                    '&nbsp;&nbsp;&nbsp;' +
                    '<span class="tags">' + tags + '</span>' +
                '</div>' +
            '</td>' +
            '<td width="15">&nbsp;</td>' +
            '</tr></table>';
        
        return content;
    }

    this.renderRow = function(row) {
        var s = this.renderRowContent(row);
        $("#hot_results").append('<div id="hr' + row.id + '" class="result_row">' + s + '</div>');
        var name = '#hr' + row.id;
        $(name + ' .actions img')
            .css('opacity', 0.5)
            .mouseover(function() {
               $(this).css('opacity', 1.0);
            })
            .mouseout(function() {
               $(this).css('opacity', 0.5);
            });
    }

    this.updateRow = function(row) {
        var name = '#hr' + row.id;
        $(name).html(this.renderRowContent(row));
        $(name + ' .actions img')
            .css('opacity', 0.5)
            .mouseover(function() {
               $(this).css('opacity', 1.0);
            })
            .mouseout(function() {
               $(this).css('opacity', 0.5);
            });
    }

    this.updateAllRows = function() {
        for (var i = 0; i < this.currRows.length; i++) {
            this.currRows[i].ord = i+1;
            this.updateRow(this.currRows[i]);
        }
    }

    this.highlightRow = function(s) {
        for (var i = 0; i < this.currRows.length; i++) {
            var r = this.currRows[i];
            if (r.extID == s) {
                var row = $("#hr" + r.id);
                $("html,body").animate({scrollTop: row.offset().top}, 1000, function() {
                row
                    .fadeOut("slow", function() {
                        $(this).fadeIn("slow").css('backgroundColor', '#f5f5f5');
                    });
                });
            }
        }
    }

    this.renderRows = function(rows) {
        if (this.currRows.length == 0) {
            for (var i = 0; i < rows.length; i++) {
                this.renderRow(rows[i]);
            }
            this.currRows = rows;
            this.tidData = setTimeout("hot.fetchData()", this.fetchInterval);
            if (window.location.hash != '')
                this.highlightRow(window.location.hash.substring(1));
            return;
        }

        this.targetRows = rows;
        this.transition();
    }

    this.transition = function() {
        if (!this.idle) {
            this.tidTransition = setTimeout("hot.transition()", this.transitionInterval);
            return;
        }

        var i, j;
        
        for (i = 0; i < this.currRows.length; i++) {
            r1 = this.currRows[i];
            for (j = 0; j < this.targetRows.length; j++) {
                r2 = this.targetRows[j];
                if ((r1.showTitle + r1.url) == (r2.showTitle + r2.url)) {
                    var rowChanged = false;
                    if (r1.abs != r2.abs) {
                        r1.abs = r2.abs;
                        rowChanged = true;
                    }
                    if (r1.timestamp != r2.timestamp) {
                        r1.timestamp = r2.timestamp;
                        rowChanged = true;
                    }
                    if (rowChanged)
                        this.updateRow(r1);
                }
            }
        }

        var hasChanges = false;
        var r1, r2;

        if (this.delRow == null && this.addRow == null) {
            for (i = 0; i < this.currRows.length; i++)
                this.currRows[i].delRow = true;

            for (i = 0; i < this.targetRows.length; i++)
                this.targetRows[i].addRow = true;

            for (i = 0; i < this.currRows.length; i++) {
                r1 = this.currRows[i];
                for (j = 0; j < this.targetRows.length; j++) {
                    r2 = this.targetRows[j];
                    if ((r1.showTitle + r1.url) == (r2.showTitle + r2.url)) {
                        r1.delRow = false;
                        r2.addRow = false;
                        if (i != j) {
                            if (i > j)
                                r1.trend = 'up';
                            else if (i < j)
                                r1.trend = 'down';
                            r2.fromPos = i;
                            r2.toPos = j;
                            hasChanges = true;
                            break;
                        }
                    }
                }
            }

            for (i = 0; i < this.currRows.length; i++) {
                r1 = this.currRows[i];
                if (r1.delRow) {
                    r1.fromPos = i;
                    r1.toPos = this.rowsPerPage-1;
                    hasChanges = true;
                    this.delRow = r1;
                    this.delRow.moved = false;
                    this.delRow.changed = false;
                    break;
                }
            }

            for (i = 0; i < this.targetRows.length; i++) {
                r2 = this.targetRows[i];
                if (r2.addRow) {
                    r2.fromPos = this.rowsPerPage-1;
                    r2.toPos = i;
                    hasChanges = true;
                    this.addRow = r2;
                    break;
                }
            }
        }

        if (this.addRow != null && this.delRow != null) {
            if (!this.delRow.moved) {
                this.moveRow(this.delRow.fromPos, this.delRow.toPos);
                this.delRow.moved = true;
            } else if (!this.delRow.changed) {
                this.changeRows(this.addRow, this.delRow);
                this.delRow.changed = true;
            } else {
                this.moveRow(this.addRow.fromPos, this.addRow.toPos);
                this.addRow.fromPos = null;
                this.addRow.toPos = null;
                this.delRow.fromPos = null;
                this.delRow.toPos = null;
                this.addRow = null;
                this.delRow = null;
            }
            return;
        }

        if (!hasChanges) {
            this.tidData = setTimeout("hot.fetchData()", this.fetchInterval);
            return;
        }

        var max = 0;
        var fromPos = -1;
        var toPos = -1;
        var r;
        for (i = 0; i < this.targetRows.length; i++) {
            r = this.targetRows[i];
            if (r.fromPos != r.toPos) {
                var chg = Math.abs(r.fromPos - r.toPos);
                if (chg > max) {
                    max = chg;
                    fromPos = r.fromPos;
                    toPos = r.toPos;
                }
                r.fromPos = null;
                r.toPos = null;
            }
        }

        this.moveRow(fromPos, toPos);
    }

    this.changeRows = function(addRow, delRow) {
        var pos = addRow.fromPos;
        var rows = $("#hot_results").children();
        var r = rows.eq(pos+1);

        addRow.id = this.currRows[pos].id;
        this.currRows[pos] = addRow;

        r.fadeOut("slow", function() {
            $(this).html(hot.renderRowContent(addRow));
            $(this).fadeIn("slow", function() { 
                hot.updateAllRows();
                hot.tidTransition = setTimeout("hot.transition()", hot.transitionInterval);
            });
        });
    }

    this.moveRow = function(fromPos, toPos) {
        if (fromPos == toPos) {
            this.tidTransition = setTimeout("hot.transition()", hot.transitionInterval);
            return;
        }

        var arr = new Array();
        if (fromPos < toPos) {
            arr = arr.concat(this.currRows.slice(0, fromPos));
            arr = arr.concat(this.currRows.slice(fromPos+1, toPos+1));
            arr.push(this.currRows[fromPos]);
            arr = arr.concat(this.currRows.slice(toPos+1));
        } else {
            arr = arr.concat(this.currRows.slice(0, toPos));
            arr.push(this.currRows[fromPos]);
            arr = arr.concat(this.currRows.slice(toPos, fromPos));
            arr = arr.concat(this.currRows.slice(fromPos+1));
        }

        fromPos++;toPos++;

        this.currRows = arr;

        var rows = $("#hot_results").children();
        var fromRow = rows.eq(fromPos);
        var toRow = rows.eq(toPos);
        var dy = fromRow.position().top - toRow.position().top;
        var dy2;
        var movingRows;

        if (fromPos < toPos) {
            movingRows = rows.slice(fromPos+1, toPos+1);
            dy2 = rows.eq(fromPos+1).position().top - fromRow.position().top;
        } else {
            toRow = rows.eq(toPos-1);
            movingRows = rows.slice(toPos, fromPos);
            dy2 = rows.eq(fromPos-1).position().top - fromRow.position().top;
        }

        fromRow
            .fadeOut("fast")
            .fadeIn("fast", function() {
            $(this)
                .queue(function() {
                    $(this)
                        .css("position", "relative")
                        .css("backgroundColor", "#f5f5f5")
                        .css("borderBottom", "0px #555 dashed")
                        .css("borderTop", "0px #555 dashed")
                        .css("zIndex", "1");
                    $(this).dequeue();
                })
                .queue(function() {
                    var speed = 1000;
                    $(this).animate({top: "-=" + dy}, speed);
                    movingRows
                        .css("position", "relative")
                        .animate({top: "-=" + dy2}, speed);
                    $(this).dequeue();
                })
                .queue(function() {
                    movingRows
                        .css("position", "")
                        .css("top", "");
                    $(this)
                        .insertAfter(toRow)
                        .css("position", "")
                        .css("top", "")
                        .css("borderBottom", "0px")
                        .css("borderTop", "0px")
                        .css("backgroundColor", "#fff")
                        .css("zIndex", "0");
                    hot.updateAllRows();
                    hot.tidTransition = setTimeout("hot.transition()", hot.transitionInterval);
                    $(this).dequeue();
                });
            });
    }

    this.findRowById = function(id) {
        for (var i in this.currRows)
            if (this.currRows[i].id == id)
                return this.currRows[i];
        return null;
    }

    this.runSortBy = function(sortBy) {
        if (this.sortBy == sortBy)
            return;
        location.href = 'index.jsp?sortby=' + sortBy;
    }

    this.goToCategory = function(category) {
        if (!this.isHome && category == this.category)
            return;
        window.location = 'index.jsp?source=' + this.source + '&category=' + category;
    }

    this.goToSource = function(source) {
        if (!this.isHome && source == this.source)
            return;
        window.location = 'index.jsp?source=' + source + '&category=' + this.category;
    }

    this.renderAd = function(ad) {
        var s =
            '<div class="ad">' +
                '<div class="title">' +
                    '<a href="' + ad.url + '" onClick="visitPage(\'' + ad.url + '\',\'ads\')" target="_blank">' + ad.title + '</a>' +
                '</div>' +
                '<div class="snippet">' +
                    ad.desc +
                '</div>' +
                '<div class="url">' +
                    '<a href="' + ad.url + '" onClick="visitPage(\'' + ad.url + '\',\'ads\')" target="_blank">' + ad.showURL + '</a>' +
                '</div>' +
            '</div>';
        return toReturn;
    }

    this.showAds = function(data) {
        if (data.ads.length == 0)
            return;
        var s = '';
    	for (i in data.ads)
            s += this.renderAd(data.ads[i]);
        $("#ads_cont").html(s);
        $(".segment_ads").fadeIn();
    }

    this.onShow = function(isHome) {
        this.isHome = isHome;

        if (HasArgument('category'))
            this.category = GetArgumentCategory();
        else
            this.category = 'All';

        $("#search_box").css('color', '#999').val('Search Web...').focus(function(){
            $(this).css('color', '#000').val('');
        });

        if (!isHome) {
            if (HasArgument('source'))
                this.source = GetArgumentSource() == 'News' ? 'News' : 'All';
            else
                this.source = 'All';

            if (this.source == 'All') {
                $('#search_show_feed_all').addClass('sel');
                $('#search_show_feed_all td').eq(0).addClass('selimg');
            } else {
                $('#search_show_feed_news').addClass('sel');
                $('#search_show_feed_news td').eq(0).addClass('selimg');
            }

            search.source = this.source;
            search.category = this.category;

            var e = $('.bar #' + this.category);
            if (e.length == 0) {
                this.category = 'All'
                e = $('.bar #' + this.category);
            }
            e.addClass('sel');
            e.parent().prev().hide();
            e.parent().next().hide();

            this.fetchPage();
        }

        this.getHotTopics();
        this.tidHotTopics = setInterval("hot.getHotTopics();", 180000);
        if (!HasArgument('query') && HasArgument('category')) {
            $.getJSONExt('/a', { cat : this.category },
                function(data) {
                    hot.showAds(data);
        	}, 
                function() {}
            );
        }
    }

    this.onHide = function() {
        clearTimeout(this.tidData);
        clearTimeout(this.tidTransition);
    }

    this.init = function() {       
        if (HasArgument('sortby'))
            this.sortBy = GetArgumentSortBy();

        $(document).mousemove(function() {
            if (hot.tidIdle != -1)
                clearTimeout(hot.tidIdle);
            hot.idle = false;
            hot.tidIdle = setTimeout("hot.idle = true;", hot.idleInterval);
        });
    }

    this.init = function() {  
        if (HasArgument('sortby'))
            this.sortBy = GetArgumentSortBy();

        $(document).mousemove(function() {
            if (hot.tidIdle != -1)
                clearTimeout(hot.tidIdle);
            hot.idle = false;
            hot.tidIdle = setTimeout("hot.idle = true;", hot.idleInterval);
        });
        
    }

}

var hot = new Hot();
