/**
 * A class to parse color values
 * @author Stoyan Stefanov <sstoo@gmail.com>
 * @link   http://www.phpied.com/rgb-color-parser-in-javascript/
 * @license Use it if you like it
 */
function RGBColor(color_string)
{
    this.ok = false;

    // strip any leading #
    if (color_string.charAt(0) == '#') { // remove # if any
        color_string = color_string.substr(1,6);
    }

    color_string = color_string.replace(/ /g,'');
    color_string = color_string.toLowerCase();

    // array of color definition objects
    var color_defs = [
        {
            re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
            example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
            process: function (bits){
                return [
                    parseInt(bits[1]),
                    parseInt(bits[2]),
                    parseInt(bits[3])
                ];
            }
        },
        {
            re: /^(\w{2})(\w{2})(\w{2})$/,
            example: ['#00ff00', '336699'],
            process: function (bits){
                return [
                    parseInt(bits[1], 16),
                    parseInt(bits[2], 16),
                    parseInt(bits[3], 16)
                ];
            }
        },
        {
            re: /^(\w{1})(\w{1})(\w{1})$/,
            example: ['#fb0', 'f0f'],
            process: function (bits){
                return [
                    parseInt(bits[1] + bits[1], 16),
                    parseInt(bits[2] + bits[2], 16),
                    parseInt(bits[3] + bits[3], 16)
                ];
            }
        }
    ];

    // search through the definitions to find a match
    for (var i = 0; i < color_defs.length; i++) {
        var re = color_defs[i].re;
        var processor = color_defs[i].process;
        var bits = re.exec(color_string);
        if (bits) {
            channels = processor(bits);
            this.r = channels[0];
            this.g = channels[1];
            this.b = channels[2];
            this.ok = true;
        }

    }

    // validate/cleanup values
    this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
    this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
    this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);

    // some getters
    this.toRGB = function () {
        return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
    }
    this.toHex = function () {
        var r = this.r.toString(16);
        var g = this.g.toString(16);
        var b = this.b.toString(16);
        if (r.length == 1) r = '0' + r;
        if (g.length == 1) g = '0' + g;
        if (b.length == 1) b = '0' + b;
        return '#' + r + g + b;
    }

    // help
    this.getHelpXML = function () {

        var examples = new Array();
        // add regexps
        for (var i = 0; i < color_defs.length; i++) {
            var example = color_defs[i].example;
            for (var j = 0; j < example.length; j++) {
                examples[examples.length] = example[j];
            }
        }
        // add type-in colors
        for (var sc in simple_colors) {
            examples[examples.length] = sc;
        }

        var xml = document.createElement('ul');
        xml.setAttribute('id', 'rgbcolor-examples');
        for (var i = 0; i < examples.length; i++) {
            try {
                var list_item = document.createElement('li');
                var list_color = new RGBColor(examples[i]);
                var example_div = document.createElement('div');
                example_div.style.cssText =
                        'margin: 3px; '
                        + 'border: 1px solid black; '
                        + 'background:' + list_color.toHex() + '; '
                        + 'color:' + list_color.toHex()
                ;
                example_div.appendChild(document.createTextNode('test'));
                var list_item_value = document.createTextNode(
                    ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
                );
                list_item.appendChild(example_div);
                list_item.appendChild(list_item_value);
                xml.appendChild(list_item);

            } catch(e){}
        }
        return xml;

    }

}



function replace_links() {	
	if (!document.getElementsByTagName){ return; }
	var anchors = document.getElementsByTagName('a');

	for (var i=0; i<anchors.length; i++){
		var anchor = anchors[i];
		
		var classAttribute = String(anchor.getAttribute('class'));
		
		if (anchor.getAttribute('href') && (Element.hasClassName(anchor, 'expansion'))){
			anchor.setAttribute('link_destination', anchor.getAttribute('href'));
			
			anchor.setAttribute('id', "expansion_" + i);
			var color = new RGBColor(anchor.getStyle("backgroundColor"));
      anchor.writeAttribute({link_color:color.toHex()});
      
			Event.observe(anchor, 'click', function(e) { show_shard(Event.element(e).getAttribute('link_destination'), 
																		Event.element(e).getStyle('background-color'), 
																		(e || window.event)); }, false);
			anchor.onclick = function(){return false;};
			anchor.setAttribute('href', '#');
		}
	}
}

function setup_the_hide_and_show_link_colors() {
  if ($('read_fragment')) {
    Event.observe($('read_fragment'), 'mouseleave', function(){hide_link_colors()});
    Event.observe($('read_fragment'), 'mouseenter', function(){show_link_colors()});
  }
}


var link_colors_are_hidden = false;
function hide_link_colors() {
  if (!link_colors_are_hidden) {
    link_colors_are_hidden = true;
    links = document.getElementsByClassName("expansion");
    links.each(function(link){
      var color = link.readAttribute('link_color');
      new Effect.Highlight(link, {startcolor:color, endcolor:"#000000", restorecolor:'#000000',
                                  duration:0.3, queue: {position:'end', scope: link.id}});
    });
  }
}

function show_link_colors() {
  if (link_colors_are_hidden) {
    link_colors_are_hidden = false;
    links = document.getElementsByClassName("expansion");
    links.each(function(link){
      var color = link.readAttribute('link_color');
      new Effect.Highlight(link, {startcolor:'#000000', endcolor:color, restorecolor:color,
                           duration:0.3, queue: {position:'end', scope: link.id}});
    });
  }
}

Event.onDOMReady(function(){start_the_reading()});
function start_the_reading() {
	replace_links();
	setup_the_hide_and_show_link_colors();
}

function show_shard(the_link, a_color, an_event) {
	Element.hide('connector'); Element.hide('extra'); Element.hide('extra_top');
	var yCoord = Event.pointerY(an_event);
	show_connector(yCoord, a_color);
	new Ajax.Updater('update_area', 
							 	the_link, 
							 	{asynchronous:true, evalScripts:true, 
									onComplete:function(request)
								{slide_and_reveal_extra(yCoord);} 
								});					
}

function slide_and_reveal_extra(yCoord) {
	new Effect.Appear('extra'); new Effect.Appear('extra_top');
	var extra = $('extra');	
	var extra_top = $('extra_top');
	extra.style.position = 'absolute';
	extra_top.style.position = 'absolute';
	extra.setStyle({top:(yCoord - 26 + 'px')});
	extra_top.setStyle({top:(yCoord-46 + 'px')});
	return false;
}

function show_connector(yCoord, a_color) {
	var conn = $('connector');
	Element.hide(conn);
	conn.setStyle({ position: 'absolute', 
									top: yCoord - 10 + 'px', 
									background: a_color + ' url(/images/connector.png) top right',
									left: (((document.width || document.body.offsetWidth) - 820) + 'px') });
	Element.show(conn);
	new Effect.Move($('connector'), {x:250, y:0});
}