/**
 * @param Array params
 *   - string name - keyword name
 *   - string url     - full URL (ex. http://google.com)
 *   - string id      - from db: keyword.id
 */
function CKeyword (params)
{
	this.p = params;
	var r = new RegExp();
	r.compile(
		"(" +
			"\\W" + params.name + "\\W" +
				"|" +
			"^" + params.name + "\\W" +
				"|" +
			"\\W" + params.name + "$" +
		")", "gim");
	this.p.regexp = r;
}

/**
 * @param array params
 *   - string tag - id of html element to parse and add context ads
 *   - integer limit
 */

function ContextAds (params)
{
	// already sorted by price by php
	this.campaigns = new Array();

	this.p = params;

	this.tag = this.p.tag;
	this.regexp = '';
	this.textNodes = Array();
	this.impressions = Array();

	this.matches = Array();
	/**
	 * Add keyword
	 *
	 * @param cKeyword campaign
	 */
	this.add = function (campaign)
	{
		this.campaigns.push(campaign);

	};

	this.showAds = function()
	{
		if (this.tag == "body")
		{
			this._traverse(window.document);
		}
		else
		{
			this._traverse(document.getElementById(this.tag));
		}

		this.insertKeywords2();

	};

	this.insertKeywords2 = function()
	{
		var tmp = 0;
		var pos2;
		// remove keywords that aren't in text nodes and find matches
		for (var i = 0; i < this.campaigns.length; ++i)
		{
			var keyword = this.campaigns[i].p;
			var found = false;

			for (var j=0; j < this.textNodes.length; ++j)
			{
				var str = this.textNodes[j].nodeValue;
				var add_index = 0;
				do
				{
					var pos = str.search(keyword.regexp);
					if (pos >= 0)
					{
						found = true;
						if (!(this.matches[i] instanceof Array))
						{
							this.matches[i]	= Array();
						}
						//                            (nodeIndex, keywordIndex, position in node)
						if (pos == 0)
							tmp = 0;
						else
							tmp = 1;
							
						pos2 = pos + add_index + tmp;

						keyword_str = str.substr(pos2, keyword.name.length);

						this.matches[i].push(new Array(j, i, pos2, keyword_str));

						var newpos = pos + keyword.name.length + 1;
						add_index += newpos;
						str = str.substr(newpos);
					}
				}
				while (pos >= 0);
			}

			if (found == false)
			{
				this.campaigns.splice(i, 1);
				--i;
			}
		}

		var dataToUse = new Array();
		do
		{
			process = false;

			for (var i=0; i < this.matches.length && dataToUse.length < this.p.limit; i++)
			{
				if (data = this.matches[i].shift())
				{
					process = true;
					dataToUse.push(data);
				}
			}
		}
		while (process);

		// --------- group by node id
		// sort by node id
		dataToUse.sort(function(a, b)
		{
			return a[0] - b[0];
		});

		var dataToUse2 = Array();
		var len = dataToUse.length;

		var next = null;
		var curr = null;
		var idx = 0;

		for (var i=0; i < len; ++i)
		{
			if (i == len - 1)
			{
				next = null;
			}
			else
			{
				next = dataToUse[i+1];
			}
			curr = dataToUse[i];

			if (!(dataToUse2[idx] instanceof Array))
			{
				dataToUse2[idx] = new Array();
			}

			dataToUse2[idx].push(curr);

			if (next && curr[0] != next[0])
			{
				idx++;
			}
		}

		var len = dataToUse2.length;
		var startpos = 0;
		var endpos = 0;
		var len2 = 0;

		for (var i=0; i < len; ++i)
		{
			len2 = dataToUse2[i].length;

			var node = this.textNodes[dataToUse2[i][0][0]];
			var parent = node.parentNode;
			var str = node.nodeValue;
			var startpos = 0;

			if (len2 > 1)
			{
				dataToUse2[i].sort(function(a, b)
				{
					return a[2] - b[2];
				});
			}

			for (var j=0; j < len2; j++)
			{
				var keyword = this.campaigns[dataToUse2[i][j][1]].p;
				var endpos = dataToUse2[i][j][2];
				var substr = str.substring(startpos, endpos);

				var n = document.createTextNode(substr);
				startpos = endpos + keyword.name.length;

				parent.insertBefore(n, node);

				n = document.createElement('a');
				n.setAttribute("href", keyword.url);
				n.style.fontWeight = "bold";
				n.style.textDecoration = "underline";
				n.style.borderBottom = "1px solid";

				n.innerHTML = dataToUse2[i][j][3];
				parent.insertBefore(n, node);
			}

			if (startpos < str.length)
			{
				n = document.createTextNode(str.substring(startpos));
				parent.insertBefore(n, node);
			}

			parent.removeChild(node);


			this.addImpression(keyword.id, keyword.wk_id);
		}


		this.sendImpressions();
	}

	this._traverse = function(el)
	{
		if (el.childNodes.length > 0)
		{
			for(var j=0; el.childNodes[j] && el.nodeName != "TEXTAREA" && el.nodeName != "SCRIPT" && el.nodeName != "A" && el.nodeName != "H1" && el.nodeName != "H2" && el.nodeName != "H3" && el.nodeName != "H4" && el.nodeName != "H5"; ++j)
			{
				this._traverse(el.childNodes[j]);
			}
		}
		else
		{
			if(el.nodeName == "#text")
			{
				this.textNodes.push(el);
			}
		}
	};

	this.addImpression = function(keyword_id, website_keyword_id)
	{
		this.impressions.push({wk: website_keyword_id, k: keyword_id});
	}

	this.sendImpressions = function()
	{
		var l = this.impressions.length;
		var link = '';
		
		for (var i = 0; i < l; ++i)
		{
			if (i == 0)
				link += '?';
			else
				link += '&';

			link += 'k[' + this.impressions[i].wk + ']=' + this.impressions[i].k;
		}

		var req_image = new Image();
		req_image.src = this.p.url + link + '&rand=' + Math.random() + '_' + (new Date()).getTime();
	}
}