/**
 * JavaScript Pixel Picker
 *
 * @author  Jan Odvarko, http://odvarko.cz
 * @created 2010-02-06
 * @updated 2010-02-10
 */


"use strict";


/*
 * Initialize <img> element as pickable map
 *
 * @arg mixed - element's ID or element itself
 */
var PixelPicker = function (imgElement) {

	var ppInstance = this, imgEl;

	function onMouseUp(ev) {
		var x, y, reqURL, imgPath;
		if (!ev) {
			ev = window.event;
		}
		x = ev.layerX ? ev.layerX : (ev.offsetX ? ev.offsetX : 0);
		y = ev.layerY ? ev.layerY : (ev.offsetY ? ev.offsetY : 0);

		imgPath = PixelPicker.mergePaths(
			window.location.pathname,
			imgEl.src.replace(/^[0-9a-z+.\-]*:\/\/[^\/?#]*/i, '')
		);

		reqURL = PixelPicker.getpixelScript;
		reqURL = reqURL.replace('$x', x);
		reqURL = reqURL.replace('$y', y);
		reqURL = reqURL.replace('$img', encodeURIComponent(imgPath));

		PixelPicker.ajaxRequest('GET', reqURL, function (respObj) {
			ppInstance.responseHandler(respObj.responseText);
		});
	}

	imgEl = PixelPicker.getElement(imgElement);
	if (PixelPicker.getRealStyle(imgEl, 'position').toLowerCase() === 'static') {
		imgEl.style.position = 'relative';
	}
	PixelPicker.attachEvent(imgEl, 'mouseup', onMouseUp);
	imgEl.style.cursor = 'crosshair';

};


/*
 * Return the element of specified ID
 *
 * @arg mixed - element's ID or element itself
 */
PixelPicker.getElement = function (mixed) {
	return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
};


/*
 * Return element's computed style
 *
 * @arg object - element we concern in
 * @arg string - CSS property name (camelCase)
 */
PixelPicker.getRealStyle = function (el, prop) {
	if (window.getComputedStyle) {
		return document.defaultView.getComputedStyle(el, null).getPropertyValue(prop);
	} else if (el.currentStyle) {
		return el.currentStyle[prop];
	} else {
		return false;
	}
};


/*
 * Register an event
 *
 * @arg object - element we concern in
 * @arg string - name of the event (without leading 'on...')
 * @arg object - handling function
 */
PixelPicker.attachEvent = function (el, ev, handler) {
	if (el.addEventListener) {
		el.addEventListener(ev, handler, false);
	} else if (el.attachEvent) {
		el.attachEvent('on' + ev, handler);
	}
};


/*
 * Merges two paths according to the specification
 *
 * @arg string - path1
 * @arg string - path2
 * @see RFC3986
 */
PixelPicker.mergePaths = function (path1, path2) {

	function removeDotSegments(path) {
		var out = '', rm;
		while (path) {
			if (path.substr(0, 3) === '../' || path.substr(0, 2) === './') {
				path = path.replace(/^\.+/, '').substr(1);
			} else if (path.substr(0, 3) === '/./' || path === '/.') {
				path = '/' + path.substr(3);
			} else if (path.substr(0, 4) === '/../' || path === '/..') {
				path = '/' + path.substr(4);
				out = out.replace(/\/?[^\/]*$/, '');
			} else if (path === '.' || path === '..') {
				path = '';
			} else {
				rm = path.match(/^\/?[^\/]*/)[0];
				path = path.substr(rm.length);
				out = out + rm;
			}
		}
		return out;
	}

	if (path2.substr(0, 1) === '/') {
		return removeDotSegments(path2);
	} else {
		return removeDotSegments(path1.replace(/[^\/]+$/, '') + path2);
	}

};


/*
 * Lightweight AJAX implementation
 *
 * @arg string - request method: GET or POST
 * @arg string - request URL (incl. query string)
 * @arg object - response handler (takes request object as an argument)
 */
PixelPicker.ajaxRequest = function (method, url, handler) {

	var reqObj, pathname, params, pos, i, headers = [];

	function createXMLHttpObject() {
		try {
			return new XMLHttpRequest();
		} catch (e) {}
		try {
			return new ActiveXObject('Msxml2.XMLHTTP');
		} catch (e) {}
		try {
			return new ActiveXObject('Msxml3.XMLHTTP');
		} catch (e) {}
	}

	if ((pos = url.indexOf('?')) !== -1) {
		pathname = url.substr(0, pos);
		params = url.substr(pos + 1);
	} else {
		pathname = url;
		params = null;
	}

	reqObj = createXMLHttpObject();

	if (handler) {
		reqObj.onreadystatechange = function () {
			if (reqObj.readyState === 4) {
				if (reqObj.status === 200) {
					handler(reqObj);
				} else {
					// Not HTTP 200
				}
			}
		};
	}

	switch (method.toUpperCase()) {
	case 'GET':
		reqObj.open('GET', pathname + '?' + params, true);
		reqObj.send(null);
		break;

	case 'POST':
		reqObj.open('POST', pathname, true);
		reqObj.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
		reqObj.setRequestHeader('content-length', params === null ? 0 : params.length);
		reqObj.setRequestHeader('connection', 'close');
		reqObj.send(params);
		break;
	}

};

