Function.prototype.bind = function(obj) {
	var method = this,
	temp = function() {
		return method.apply(obj, arguments);
	};

	return temp;
}

ClipCore = function (gateway_path, cookie_area_id)
{
	if (!gateway_path)
		return false;
	
	if (!cookie_area_id && !document.body)
		return false;
	
	var _gateway_path = gateway_path;
	var _cookie_area_id = cookie_area_id;
	var _is_conn_avail = false;
	var _conn_failed_handler = null;
	var _clip_key = '';
	// var _is_key_checked = false;
	var _response_format = '';
	var _response_formats_allowed = {rss: 'rss', atom: 'atom', json: 'json'};
	var _requests = {};
	var _request_max_id = {};
	var _domains = [];
	
	var getHttpRequestObj = function ()
	{
		var xmlhttp = null;
		
		if (window.XMLHttpRequest)
		{ // Mozilla, etc.
			xmlhttp = new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{ // IE
			xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
		
		return xmlhttp;
	}
	
	var loadConfig = function ()
	{
		getCookie();
	}
	
	var getCookie = function ()
	{
		var cookie = document.cookie;

		if (cookie.indexOf('clip_key') != -1)
		{
			var startpos = cookie.indexOf('clip_key') + 'clip_key'.length+1;
			var endpos = cookie.indexOf(';', startpos);
			if (endpos == -1)
				endpos = cookie.length;
			
			_clip_key = decodeURIComponent(cookie.substring(startpos,endpos));
		}
		else
			_clip_key = '';
	}
	
	var setCookie = function ()
	{
		var expires = new Date();
		expires.setTime(expires.getTime() + 1000 * 60 * 60 * 24 * 365 * 20); // expiry after 20 years
		
		var domain = window.location.hostname.split('.');
		var domain_str = '';
		var idx = 0;
		if (domain[0] == 'www')
			idx = 1;
		for (var i=idx; i < domain.length; i++)
			domain_str += '.'+domain[i];
		
		document.cookie = 'clip_key=' + encodeURIComponent(_clip_key) + '; path=/; expires=' + expires.toGMTString() + "; domain="+domain_str;
	}
	
	var syncDomainCookies = function ()
	{
		var cookie_area_ele = null;
		if (_cookie_area_id)
		{
			cookie_area_ele = document.getElementById(_cookie_area_id);
			cookie_area_ele.style.display = 'none';
			cookie_area_ele.innerHTML = '';
		}
		else
			cookie_area_ele = document.body;
		
		for (var i = 0; i < _domains.length; i++)
		{
			var domain = _domains[i];
			var path = 'http://'+decodeURIComponent(domain['name']) + decodeURIComponent(domain['cookie_update_path']) + '?clip_key=' + _clip_key + '&validation_key=' + decodeURIComponent(domain['validation_key']);
			
			var ele = document.createElement('img');
			ele.src = path;
			ele.style.display = 'none';
			
			cookie_area_ele.appendChild(ele);
		}
	}
	
	var sendRequest = function (action, data, listener)
	{
		if (!data)
			data = {};
		var data_str = '';
		
		data['response_format'] = _response_format;
		for (var key in data)
		{
			if (data[key])
			{
				if (data_str)
					data_str += '&';
				
				data_str += key+'='+data[key];
			}
		}
		
		var idx = setResponseListener(action, listener);
		data_str += '&action=' + action;
		_requests[action][idx]['http_request'].open('POST', _gateway_path, true);
		_requests[action][idx]['http_request'].setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		_requests[action][idx]['http_request'].send(data_str);
		
		return _requests[action][idx]['id']; // request_id for tracing action
	}
	
	var responseHandler = function ()
	{
		for (var action in _requests)
		{
			for (var i = 0; i < _requests[action].length; i++)
			{
				if (i < 0)
					break;
				
				var http_request = _requests[action][i]['http_request'];
				var listener = _requests[action][i]['listener'];
				var req_id = _requests[action][i]['id'];
				if (http_request.readyState == 4)
				{
					var response = null;
					var is_xml_response = false;
					if (http_request.status == 200 || http_request.status == 304)
					{
						if (_response_format == _response_formats_allowed.json)
						{
							response = http_request.responseText;
						}
						else
						{
							response = http_request.responseXML;
							is_xml_response = true;
						}
					}
					checkConnection(response, is_xml_response);
					if (!_is_conn_avail)
						response = null;
					
					_requests[action].splice(i, 1);
					i--;
					
					listener(response, req_id);
				}
			}
		}
	}
	
	var setResponseListener = function (action, listener)
	{
		var new_idx = null;
		if (!_requests[action])
		{
			new_idx = 0;
			_requests[action] = [];
		}
		else
		{
			new_idx = _requests[action].length;
		}
		
		if (!_request_max_id[action])
			_request_max_id[action] = 1;
		else
			_request_max_id[action]++;
		
		_requests[action][new_idx] = {};
		_requests[action][new_idx]['id'] = _request_max_id[action];
		_requests[action][new_idx]['http_request'] = getHttpRequestObj();
		_requests[action][new_idx]['http_request'].onreadystatechange = responseHandler;
		_requests[action][new_idx]['listener'] = listener;
		
		return new_idx;
	}
	
	var checkConnection = function (response_src, is_xml)
	{
		if (response_src)
		{
			var response = { 'clip_key': '' };
			var is_error = false;
			if (is_xml)
			{
				var error_ele = response_src.getElementsByTagName('error');
				if (error_ele.length > 0)
				{
					if (error_ele[0].childNodes[0].nodeValue && error_ele[0].childNodes[0].nodeValue == 1)
						is_error = true;
				}
				
				var clip_key_ele = response_src.getElementsByTagName('clip_key');
				if (clip_key_ele.length > 0)
				{
					response.clip_key = clip_key_ele[0].childNodes[0].nodeValue;
				}
				
				var domains_ele = response_src.getElementsByTagName('domain');
				if (domains_ele.length > 0)
				{
					response['domains'] = [];
					for (var i = 0; i < domains_ele.length; i++)
					{
						var domain = {};
						domain[domains_ele[i].childNodes[0].nodeName] = domains_ele[i].childNodes[0].childNodes[0].nodeValue;
						domain[domains_ele[i].childNodes[1].nodeName] = domains_ele[i].childNodes[1].childNodes[0].nodeValue;
						domain[domains_ele[i].childNodes[2].nodeName] = domains_ele[i].childNodes[2].childNodes[0].nodeValue;
						response.domains.push(domain);
					}
				}
			}
			else
			{
				response = eval('('+response_src+')');
				
				if (response.error === 1)
					is_error = true;
				
				_domains = response.domains;
			}
			
			if (!is_error)
			{
				if (response.clip_key != _clip_key)
				{
					_clip_key = response.clip_key;
					_domains = response.domains;
					
					setCookie();
					syncDomainCookies();
				}
				_is_conn_avail = true;
			}
			else
				_is_conn_avail = false;
		}
		else
			_is_conn_avail = false;
		
		if (!_is_conn_avail && _conn_failed_handler)
		{
			_conn_failed_handler();
		}
	}
	
	this.fetchItems = function (criteria, listener)
	{
		return sendRequest('get_item', criteria, listener);
	}
	
	this.addItem = function (info, listener)
	{
		return sendRequest('add_item', info, listener);
	}
	
	this.removeItem = function (clip_item_id, listener)
	{
		var info = {'clip_item_id': clip_item_id};
		return sendRequest('delete_item', info, listener);
	}

	this.removeItems = function (clip_item_id, listener)
	{
		var info = {'clip_item_id': clip_item_id};
		return sendRequest('delete_items', info, listener);
	}
	
	this.updateItem = function (info, listener)
	{
		if (!info['clip_item_id'])
			return false;
		
		return sendRequest('update_item', info, listener);
	}
	
	this.setResponseFormat = function (format)
	{
		if (_response_formats_allowed[format])
		{
			_response_format = _response_formats_allowed[format];
			return true;
		}
		else
			return false;
	}
	
	this.setConnectionFailedHandler = function (handler_func)
	{
		if (typeof handler_func == 'function')
		{
			_conn_failed_handler = handler_func;
			return true;
		}
		
		return false;
	}
	
	loadConfig();
}
