//
// PersonalDNA Swatch code
// now for Personal PersonalDNA use
//

function Tile() {
    var htmlArray = new Array();

    this.begin = begin;
    this.toString = toString;
    this.addBlock = addBlock;
    var width, height;
    var marginTop, marginBottom;
    var marginLeft, marginRight;
        
    function begin(w, h, top, bot, lef, rig) {
        width = w;
        height = h;
        marginTop = top;
        marginBottom = bot;
        marginLeft = lef;
        marginRight = rig;
    }

    function toString(head, foot, linkText, isActive) {
        var tmpArray = new Array();
        tmpArray.push('<div style="');
        tmpArray.push('position: relative;overflow: hidden;');
        tmpArray.push('width: ' + (width + marginLeft + marginRight) + 'px;');
        tmpArray.push('height: ' + (height + marginTop + marginBottom) + 'px;');
        tmpArray.push('">');
        if (head) tmpArray.push(head);

        tmpArray.push(htmlArray.join(''));

        if (foot) tmpArray.push(foot);

        tmpArray.push('</div>');

		tmpArray.push(linkDivHTML(
					(width + marginLeft + marginRight), linkText, isActive));

        return tmpArray.join('');
    }

    function addBlock(x, y, w, h, name, hue, val) {
	    htmlArray.push('<div title="'); 
	    htmlArray.push(name); 
	    htmlArray.push('" style="');
        htmlArray.push('position: absolute;overflow: hidden;');
        htmlArray.push('left: ');
        htmlArray.push(Math.round(x + marginLeft) + 'px;');
        htmlArray.push('top:');
        htmlArray.push(Math.round(y + marginTop) + 'px;');
        htmlArray.push('height:');
        htmlArray.push(Math.round(h) + 'px;');
        htmlArray.push('width:');
        htmlArray.push(Math.round(w) + 'px;');

        var rgb;		
	    if (hue == "gray") {
		    rgb = htmlcolor(150-(val*1.5), 150-(val*1.5), 150-(val*1.5));
	    } else {
	        if (hue < 0) { 
	            hue = -hue;
	            val = 100 - val;
	        }
		    rgb = hsv2rgb(hue, .9, (val / 200.0) + .5);
	    }
    	
        htmlArray.push('background-color:');
        htmlArray.push(rgb);
        htmlArray.push('">'); 
        htmlArray.push('</div>');
    }
}

// TreeMap
// Derived from http://phasetwo.org/squarifiedtreemaptest.html
//
function TreeMap() {
	var nodes = new Array();
	var tile;
	var nodetotal = 0;
	var normalisefactor = 0;
	var width = 0;
	var height = 0;
	var totalarea = 0;
	var lwidth = 0;
	var lheight = 0;
	var lx = 0;
	var ly = 0;
	
	this.setWidth  = setWidth;
	this.setHeight = setHeight;
	this.draw      = draw;
	this.addNode   = addNode;

	function addNode(node) {
		nodes.push(node)
	}

	function setWidth(w) {
		width = w;
		lwidth = w;
		totalarea = width * height;
	}

	function setHeight(h) {
		height = h;
		lheight = h;
		totalarea = width * height;
	}

	function draw(linkText, isActive) {
	    tile = new Tile();
        tile.begin(width, height, 0, 0, 0, 0);
        	    
		heapSort();
		normalise();

        // clone nodes
		var narr = nodes.slice(0,nodes.length);

        // pull off first node into the row array
		var row = narr.splice(0,1);
		
		// recursively layout
		squarify(narr,row,shortSide());
		
		
        return tile.toString(false, false, linkText, isActive);
	}

	function normalise() {
		for (var i=0 ; i <nodes.length; i++) {
			var node = nodes[i];
			var areaperc = node.size / nodetotal;
			node.size = areaperc * totalarea;
		}
	}

	function shortSide() {
	    return lwidth < lheight ? lheight : lwidth;
	}

	function squarify(nodes, row, w) {	
		if (nodes.length > 0) {
			var node = nodes[0];
			var newrow = row.concat(node);

			if (worst(row, w) > worst(newrow, w)) {
				nodes.shift();
				squarify(nodes, newrow, w);
			} else {
				layout(row);
				var row = nodes.splice(0,1);
				squarify(nodes,row, shortSide());
			}
		} else {
			layout(row);
		}
	}

	function worst(row,w) {
		var totalarea = sizeSum(row);
		var worstaspect = 0;

		for (var i = 0; i < row.length; i++) {
			var aspect = 0;
			var dim1 = (row[i].size / totalarea) * w;
			var dim2 = row[i].size / dim1;

			if (dim1 > dim2) {
				aspect = dim1/dim2;
			} else {
				aspect = dim2/dim1;
			}
			if (worstaspect < aspect)
				worstaspect = aspect;
		}

		return worstaspect;
	}

	function layout(row) {
		if (row.length ==0)
			return

		var rowx = lx;
		var rowy = ly;
		var rowtotal = sizeSum(row);

		if (shortSide() == lheight) { // vertical
			for (var i = 0; i < row.length; i++) {
				var bwidth = (row[i].size / rowtotal) * lwidth;
				var bheight = row[i].size / bwidth;

				// fudge rounding error //
				if (i < row.length-1) {
					var iwidth = Math.round(bwidth);
					var iheight = Math.round(bheight);
					var ar = (iwidth * iheight) - (bwidth * bheight);
					row[i+1].size += ar;
				} else {
					bwidth = lwidth + lx - rowx;
				}
				
				tile.addBlock(rowx,rowy,bwidth,bheight, row[i].name, row[i].hue, row[i].value);
				rowx += Math.round(bwidth);				
			}

			ly = ly + bheight;
			lheight = lheight - bheight;

		} else { // horizontal

			//var accumuheight = 0

			for (var i = 0; i < row.length; i++) {
				var bheight = (row[i].size / rowtotal) * lheight;
				var bwidth = row[i].size / bheight;
				
				// fudge rounding error //
				if (i < row.length-1) {
					var iwidth = Math.round(bwidth);
					var iheight = Math.round(bheight);
					var ar = (iwidth * iheight) - (bwidth * bheight);
					row[i+1].size += ar;
				} else {
					bheight = lheight + ly - rowy;
				}		

				tile.addBlock(rowx,rowy,bwidth,bheight, row[i].name, row[i].hue, row[i].value);
				rowy += Math.round(bheight);			
			}

			lx = lx + bwidth;
			lwidth = lwidth - bwidth;
		}
	}

	function sizeSum(row) {
		var rsize = 0;

		if (row.length == 0)
			return rsize;

		for (var i=0; i < row.length; i++)
			rsize += row[i].size;

		return rsize;
	}

	function row() {
		this.x = 0;
		this.y = 0;
		this.w = 0;
		this.h = 0;
	}

	function rect(x,y,w,h,o) {
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
	}

	// sort to order list biggest to smallest
	function heapSort() {
		var newarr = new Array();
		
		while(nodes.length > 0)
		{
			var biggestsize = nodes[0].size;
			var biggestindex = 0;
			
			for (var i = 1; i < nodes.length ;i++) {
				if (nodes[i].size > biggestsize) {
					biggestsize = nodes[i].size;
					biggestindex = i;
				}
			}
			newarr.push(nodes.splice(biggestindex,1)[0]);
			nodetotal += biggestsize;
		}
		nodes = newarr;
	}
}

function Node(name, sz, hue) {
    this.name = name;
	this.size = sz;
	this.value = sz;
	this.hue = hue;
}

//*** This code is copyright 2003 by Gavin Kistner, gavin@refinery.com
//*** It is covered under the license viewable at http://phrogz.net/JS/_ReuseLicense.txt

// Takes a HSV color:
// h (hue) is a float from 0 to 360
// s (saturation) and v (value) are floats between 0 and 1.
// Returns an HTML hex color string (#rrggbb).
//
function hsv2rgb(h,s,v) {
	var r, g, b, i, f, p, q, t;

	while ( h < 0) h += 360;
	h %= 360;

	s = s > 1 ? 1 : s < 0 ? 0 : s;
	v = v > 1 ? 1 : v < 0 ? 0 : v;

	if (s == 0) {
	    r=g=b=v;
	} else {
		h /=60;
		
		f = h - (i = Math.floor(h));
		p = v * (1-s);
		q = v * (1-s*f);
		t = v * (1 - s*(1-f));

		switch (i) {
			case 0: r=v; g=t; b=p; break;
			case 1: r=q; g=v; b=p; break;
			case 2: r=p; g=v; b=t; break;
			case 3: r=p; g=q; b=v; break;
			case 4: r=t; g=p; b=v; break;
			case 5: r=v; g=p; b=q; break;
		}
	}

    return htmlcolor(Math.round(r*255), Math.round(g*255), Math.round(b*255)); 
}

// Takes a rgb, returns an HTML color (#rrggbb).
//
function htmlcolor(r, g, b) {
    r = r.toString(16);
    if (r.length == 1) r = '0' + r;

    g = g.toString(16);
    if (g.length == 1) g = '0' + g;

    b = b.toString(16);
    if (b.length == 1) b = '0' + b;

    return ('#' + r + g + b).toLowerCase();
}

var traits = [
    // ORDER MATTERS - this matches the order that traits appear in the key
    {name:'conf', hue:0,title:'Confidence'},
    {name:'open', hue:150,title:'Openness'},
    {name:'extr', hue:300,title:'Extroversion'},
    {name:'empy', hue:330,title:'Empathy'},
    {name:'trus', hue:240,title:'Trust'},
    {name:'locu', hue:120,title:'Agency'},
    {name:'masc', hue:210,title:'Masculinity'},
    {name:'femn', hue:60,title:'Femininity'},
    {name:'spon', hue:180,title:'Spontenaiety'},
    {name:'styl', hue:"gray",title:'Attention to Style'},
    {name:'auth', hue:270,title:'Authoritarianism'},
    {name:'eart', hue:-30,title:'Earthy/Imaginative',flip:true},
    {name:'aefn', hue:90,title:'Functional/Aesthetic',flip:true}
];
    
/*
var traitHues = {
    conf: 0,
    eart: -30,
    femn: 60,
    aefn: 90,
    locu: 120,
    open: 150,
    spon: 180,
    masc: 210,
    trus: 240,
    auth: 270,
    extr: 300,
    empy: 330,
    styl: "gray", 
};
*/
var personalDNALink = '<a href="http://www.personaldna.com" style="font-size:x-small">personalDNA</a>';

function getPersonalDNALink(linkText, isActive) {

	if (null == linkText || '' === linkText)
		linkText = 'personalDNA';

	var linkHTML = linkText;
	if (isActive)
		linkHTML = '<a href="http://www.personaldna.com">' + linkText + '</a>';

	//	linkHTML = '<a href="http://www.personaldna.com" ' +
	//		'style="font-size:small">' + linkText + '</a>';

	return linkHTML;

}

function getTraitTitle(trait, val) {
    if (trait.flip) {
        var scaleLabels = ['Slightly', '', 'Very'];
        var title;
        if (val < 50) {            
            title = trait.name == 'aefn' ? 'Functional' : 'Imaginative';
            newVal = (50 - val) / 50.0;
        } else {
            title = trait.name == 'aefn' ? 'Aesthetic' : 'Earthy';
            newVal  = (val - 50) / 50.0;
        }
        newVal = newVal < .3 ? 0 : (newVal > .7 ? 2 : 1);
          
        return ' ' + scaleLabels[newVal] + ' ' + title;
    } else {
        var scaleLabels = ['Low','Slightly Low','Average','Slightly High','Very High'];
        newVal = Math.floor(val / 20);
        if (newVal >= scaleLabels.length) newVal = scaleLabels.length - 1;

        return ' ' + scaleLabels[newVal] + ' ' + trait.title;
    }
}


function decodeDnaKey(key) {
    var result = new Array();
    for (var i = 0; i < traits.length; i++) {
        var val = key.charCodeAt(i);
		val -= (val < 97 ? 65 : 71);
		result.push(val * 2);
    }
    return result;
}

// swatch2 says just give me the html
function personalDnaSwatchHTML(key, linkText, isActive) {
    var vals = decodeDnaKey(key);
    var width = 200, height = 200;
    var tmap = new TreeMap();
    for (var i = 0; i < traits.length; i++) {
        var trait = traits[i];
        var val = vals[i];
        if (val < 2) val = 2;       
        var fval = (trait.flip) ? Math.abs(val - 50) * 2 : val;
        tmap.addNode(new Node(getTraitTitle(trait,val), fval, trait.hue));
    }
    tmap.setWidth(width);
    tmap.setHeight(height);

    var htm = tmap.draw(linkText, isActive);
    return htm;
}


function personalDnaSwatch(key, linkText, isActive) {

	//var html = personalDnaSwatchHTML(key) +
	//	getPersonalDNALink(linkText, isActive);
	var html = personalDnaSwatchHTML(key, linkText, isActive);
	document.write(html);

}


// swatch2 says just give me the html
function personalDnaVStripHTML(key, linkText, isActive) {
    var tile = new Tile();
    var width = 30, height = 200;

    tile.begin(width, height, 18, 18, 0, 0);    

    var vals = decodeDnaKey(key);
    var total = 0;
    for (var i = 0; i < traits.length; i++) {
        var trait = traits[i];
        var val = vals[i];
        var fval = (trait.flip) ? Math.abs(val - 50) * 2 : val;
        total += fval;
    }    

    var pos = 0;
    for (var i = 0; i < traits.length; i++) {
        var trait = traits[i];
        var val = vals[i];
        if (val < 4) val = 4;
        var fval = (trait.flip) ? Math.abs(val - 50) * 2 : val;
        var size = Math.round((fval / total) * height);        
        tile.addBlock(0, pos, width, size, getTraitTitle(trait,val), trait.hue, fval);
        pos += size;
    }    

    var str = tile.toString(
        "<img src='http://www.personaldna.com/images/dna_top.gif' style='position:absolute;top:0;left:0'>", 
        "<img src='http://www.personaldna.com/images/dna_bot.gif' style='position:absolute;top:" + (height +18) + "px;left:0'>", linkText, isActive); 

    return str;

}

function personalDnaVStrip(key, linkText, isActive) {

	//var html = personalDnaVStripHTML(key) +
	//	getPersonalDNALink(linkText, isActive);
	var html = personalDnaVStripHTML(key, linkText, isActive);
	document.write(html);

}



// swatch2 says i don't think we need drawkey()
// function drawkey() {
//     document.write('<table>');
//     
//     for (var i = 0; i < traits.length; i++) {
//         var trait = traits[i];
//         document.write('<tr><td>');
//         var tile = new Tile();
//         tile.begin(32,32);
//         tile.addBlock(0,0,32,32,trait.name,trait.hue, 0);
//         document.write(tile.toString());
//         document.write('</td><td>');
//         tile = new Tile();
//         tile.begin(32,32);
//         tile.addBlock(0,0,32,32,trait.name,trait.hue, 100);
//         document.write(tile.toString());
//         document.write('</td><td>' + trait.name + '</td></tr>');
//     }
//     document.write('</table>');
// }


// swatch2 says we need a horizontal strip
function personalDnaHStripHTML(key, linkText, isActive) {
    var tile = new Tile();
    var width = 200, height = 30;

    tile.begin(width, height, 0, 0, 18, 18);    

    var vals = decodeDnaKey(key);
    var total = 0;
    for (var i = 0; i < traits.length; i++) {
        var trait = traits[i];
        var val = vals[i];
        var fval = (trait.flip) ? Math.abs(val - 50) * 2 : val;
        total += fval;
    }

    var pos = 0;
    for (var i = 0; i < traits.length; i++) {
        var trait = traits[i];
        var val = vals[i];
        if (val < 4) val = 4;
        var fval = (trait.flip) ? Math.abs(val - 50) * 2 : val;
        var size = Math.round((fval / total) * width);        
        tile.addBlock(pos, 0, size, height, getTraitTitle(trait,val), trait.hue, fval);
        pos += size;
    }

    var str = tile.toString(
        "<img src='http://www.personaldna.com/images/dna_lef.gif' style='position:absolute;top:0;left:0'>", 
        "<img src='http://www.personaldna.com/images/dna_rig.gif' style='position:absolute;top:0;left:" + (width +18) + "px;'>", linkText, isActive);

    return str;

}


function personalDnaHStrip(key, linkText, isActive) {

	//var html = personalDnaHStripHTML(key) +
	//	getPersonalDNALink(linkText, isActive);
	var html = personalDnaHStripHTML(key, linkText, isActive);
	document.write(html);

}


function linkDivHTML(width, linkText, isActive) {

	var linkHTML = getPersonalDNALink(linkText, isActive);
	var html = '<div style="position:relative; text-align:center; width:' +
				width + 'px;">' + linkHTML + '</div>';
	return html;

}
personalDnaSwatch('EDKgaTPocIBfYRW-BG-ADACA-0dbd', 'Considerate Dreamer', true);