/*
 * jQuery TagCloud 0.5.0
 * Copyright (c) 2008 Ron Valstar
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
(function ($) {
    // private variables
    var oSettings;
    var oUlCss = {};
    var oLiCss = {};
    var fGAng = 2.399963; // sphere angle in radians*pi
    // default settings
    $.tagcloud = {
        id: "TagCloud",
        version: "0.5.0",
        defaults: {
            height: null,
            type: "cloud", // "cloud", "list" or "sphere"
            sizemax: 20,
            sizemin: 10,
            colormax: "00F",
            colormin: "B4D2FF",
            seed: null, // only for type=="cloud"
            power: 0.5, // only for type=="sphere"
        },
    };
    $.fn.extend({
        tagcloud: function (_settings) {
            oSettings = $.extend({}, $.tagcloud.defaults, _settings);
            if (oSettings.seed === null)
                oSettings.seed = Math.ceil(Math.random() * 45309714203);

            switch (oSettings.type) {
                // treemap ::	http://www.jquery.info/The-TreeMap-plugin

                case "sphere":
                case "cloud":
                    oUlCss = { position: "relative" };
                    oLiCss = { position: "absolute", display: "block" };
                    break;
                case "list":
                    oUlCss = { height: "auto" };
                    oLiCss = { position: "static", display: "inline" };
                    break;
            }

            Rng.setSeed(oSettings.seed + 123456);

            return this.each(function (i, o) {
                var mUl = $(o);
                var aLi = mUl.find(">li");
                var iNumLi = aLi.length;

                var iUlW = mUl.width();
                //				var iUlH = oSettings.height===null?mUl.height():oSettings.height;
                var iUlH =
                    oSettings.height === null ? 0.004 * iUlW * iNumLi : oSettings.height;
                mUl.css({
                    width: iUlW,
                    height: iUlH,
                    listStyle: "none",
                    margin: 0,
                    padding: 0,
                });
                mUl.css(oUlCss);

                var iValMx = -2147483647;
                var iValMn = 2147483648;
                var iLastVal = -1;
                var j, x, k, mLi, iVal, iXps, iYps;
                for (j = 0; j < iNumLi; j++) {
                    mLi = $(aLi[j]);
                    iVal = mLi.attr("value") == -1 ? iLastVal++ : mLi.attr("value");
                    if (iVal > iValMx) iValMx = iVal;
                    if (iVal < iValMn) iValMn = iVal;
                    iLastVal = iVal;
                }
                var iValRn = iValMx - iValMn;

                // place on line to create minimal overlays
                var aLine = new Array();
                for (j = 0; j < iNumLi; j++) aLine[j] = j;
                for (
                    j, x, k = aLine.length;
                    k;
                    j = parseInt((Rng.rand(0, 1000) / 1000) * k),
                        x = aLine[--k],
                        aLine[k] = aLine[j],
                        aLine[j] = x
                );

                iLastVal = -1;
                for (j = 0; j < iNumLi; j++) {
                    mLi = $(aLi[j]);
                    iVal = mLi.attr("value") == -1 ? iLastVal++ : mLi.attr("value");
                    iLastVal = iVal;
                    //
                    var fPrt = (iNumLi - j - 1) / (iNumLi - 1);
                    fPrt = (iVal - iValMn) / iValRn;
                    //
                    var iSzFnt =
                        oSettings.sizemin +
                        fPrt * (oSettings.sizemax - oSettings.sizemin);
                    var sColor = colorRng(oSettings.colormin, oSettings.colormax, fPrt);
                    //
                    mLi.css({
                        fontSize: iSzFnt,
                        position: "absolute",
                        color: "#" + sColor,
                        margin: 0,
                        padding: 0,
                    })
                        .children()
                        .css({ color: "#" + sColor });
                    var iLiW = mLi.width();
                    var iLiH = mLi.height();
                    //
                    var oCss = {};
                    if (oSettings.type != "list") {
                        if (oSettings.type == "cloud") {
                            iXps = Rng.rand(0, iUlW - iLiW);
                            iYps = aLine[j] * (iUlH / iNumLi) - iLiH / 2;
                        } else {
                            var fRds = Math.pow(j / iNumLi, oSettings.power);
                            var fRad = (j + Math.PI / 2) * fGAng;
                            iXps =
                                iUlW / 2 - iLiW / 2 + 0.5 * iUlW * fRds * Math.sin(fRad);
                            iYps =
                                iUlH / 2 - iLiH / 2 + 0.5 * iUlH * fRds * Math.cos(fRad);
                        }
                        oCss.left = iXps;
                        oCss.top = iYps;
                    }
                    for (var prop in oLiCss) oCss[prop] = oLiCss[prop];
                    mLi.css(oCss);
                }
            });
        },
    });
    // Park-Miller RNG
    var Rng = new (function () {
        this.seed = 23145678901;
        this.A = 48271;
        this.M = 2147483647;
        this.Q = this.M / this.A;
        this.R = this.M % this.A;
        this.oneOverM = 1.0 / this.M;
    })();
    Rng.setSeed = function (seed) {
        this.seed = seed;
    };
    Rng.next = function () {
        var hi = this.seed / this.Q;
        var lo = this.seed % this.Q;
        var test = this.A * lo - this.R * hi;
        this.seed = test + (test > 0 ? 0 : this.M);
        return this.seed * this.oneOverM;
    };
    Rng.rand = function (lrn, urn) {
        return Math.floor((urn - lrn + 1) * this.next() + lrn);
    };
    // hex dec
    function d2h(d) {
        return d.toString(16);
    }
    function h2d(h) {
        return parseInt(h, 16);
    }
    //	function getC(s,rgb) {
    //		var aRng = [[[0,1],[1,2],[2,3]],[[0,2],[2,4],[4,6]]][s.length==3?0:1][rgb];
    //		return s.substring(aRng[0],aRng[1]);
    //	}
    function getRGB(s) {
        var b3 = s.length == 3;
        var aClr = [];
        for (var i = 0; i < 3; i++) {
            var sClr = s.substring(i * (b3 ? 1 : 2), (i + 1) * (b3 ? 1 : 2));
            aClr.push(h2d(b3 ? sClr + sClr : sClr));
        }
        return aClr;
    }
    function getHex(a) {
        var s = "";
        for (var i = 0; i < 3; i++) {
            var c = d2h(a[i]);
            if (c.length == 1) c = "0" + c; // todo: this can be better
            s += c;
        }
        return s;
    }
    function colorRng(mn, mx, prt) {
        var aMin = getRGB(mn);
        var aMax = getRGB(mx);
        var aRtr = [];
        for (var i = 0; i < 3; i++)
            aRtr.push(aMin[i] + Math.floor(prt * (aMax[i] - aMin[i])));
        return getHex(aRtr);
    }
    // // trace
    // function trace(o) {
    //   if (window.console&&window.console.log) {
    //     if (typeof(o)=="string")	window.console.log(o);
    //     else						for (var prop in o) window.console.log(prop+": "+o[prop]);
    //   }
    // };
    // set functions
    $.fn.TagCloud = $.fn.Tagcloud = $.fn.tagcloud;
})(jQuery);
