// Copyright (C) 2008  JINMEI Tatuya

// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.

// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

var AmzInfo = {
	defaults: {
		cookieName: 'amzinfo-detail',
		cookieAge: 7,		// days
		updaterId: 'Amzinfo-updater',
		nRequestItems: 10,	// max # of AWS items requested
		region: 'jp',
		keyid: '0MCVGB7CBWR8Z52PVZG2',
		assoctag: 'jinmeiorg-22',
		awsversion: '2008-08-19', // this must be consistent with XSLT
		styleurl: 'http://www.jinmei.org/xslt/aws20080819-lookup-jsonp.xsl'
	},

	onloadActions: [],
	updateAsins: [],

	doOnloadActions: function() {
		this.sendUpdateRequest();
		for (var i = 0; i < this.onloadActions.length; i++) {
			this.onloadActions[i].call();
		}
	},

	isEnabled: function() {
		var cookies = document.cookie;
		var cname  = this.defaults.cookieName + "=";
		var pos = cookies.indexOf(cname);

		if (pos != -1) {
			var start = pos + cname.length;
			var end = cookies.indexOf(";", start);
			if (end == -1)
				end = cookies.length;
			if (decodeURIComponent(cookies.substring(start, end)) ==
			    "no")
				return (false);
			else
				return (true);
		}
		return (false);
	},

	toggleDetails: function() {
		var cookieValue;
		var cookieAge  = this.defaults.cookieAge;

		cookieValue = this.isEnabled() ? "no" : "yes";
		document.cookie = this.defaults.cookieName + "=" +
			cookieValue +  "; max-age=" +
			(cookieAge * 24 * 60 * 60) + "; path=/"; 
		document.location.reload();
	},

	openAlert: function() {
		window.open('http://www.jinmei.org/amazonupdatenote.html');
	},

	updateInfo: function(asin, region) {
		var togglesuffix;
		var enabled = this.isEnabled();

		if (!region)
			region = this.defaults.region;

		togglesuffix = enabled ? 'を隠す' : 'の表示'

		document.write('[<a href="javascript:AmzInfo.toggleDetails()">'
			       + '詳細情報' + togglesuffix + '</a> | ');
		document.write('<a href="javascript:AmzInfo.openAlert()">' +
			       'セキュリティ上の注意' + '</a>]');

		if (enabled) {
			if (!this.updateAsins[region])
				this.updateAsins[region] = [];
			this.updateAsins[region].push(asin);
		} else {
			// Hide details.  We do this by modifying the DOM, so
			// defer the execution until onload time.
			var action = function() {
				var elem = document.getElementById('amzinfo-' +
								   asin +
								   '-moredesc');
				if (elem)
					AmzInfo.removeDescendants(elem);

				elem = document.getElementById('amzinfo-' + asin
							       + '-review');
				if (elem)
					AmzInfo.removeDescendants(elem);
			};
			this.onloadActions.push(action);
		}
	},

	removeDescendants: function(node) {
		if (!node.hasChildNodes())
			return;

		while (node.firstChild) {
			this.removeDescendants(node.firstChild);
			node.removeChild(node.firstChild);
		}
	},

	sendUpdateRequest: function() {
		if (!this.isEnabled())
			return;
		for (var region in this.updateAsins) {
			var i;
			var asin;
			//var resturl = 'http://xml-' + region +
				//'.amznxslt.com/onca/xml?' +
			var resturl = 'http://honnomemo.appspot.com/rpaproxy/' +
				region + '/?' +
				'Service=AWSECommerceService' +
				'&Version=' + this.defaults.awsversion +
				'&Operation=ItemLookup' +
				'&AssociateTag=' + this.defaults.assoctag +
				'&AWSAccessKeyId=' + this.defaults.keyid +
				'&IdType=ASIN' +
				'&ResponseGroup=Large' +
				'&Style=' + this.defaults.styleurl + '&ItemId=';

			for (i = 0;
			     i < this.defaults.nRequestItems;
			     i++) {
				asin = this.updateAsins[region].shift();
				if (!asin) {
					delete this.updateAsins[region];
					break;
				}
				if (i > 0)
					resturl += ',';
				resturl += asin;
			}

			if (i > 0) {
				var head;
				head = document.getElementsByTagName('head')[0];
				var script = document.createElement('script');
				script.src = resturl;
				script.id = this.defaults.updaterId;
				head.appendChild(script);
			}
			break;
		}
	},

	callback: function(arg) {
		for (var i = 0; i < arg.items.length; i++)
			this.updateItem(arg.items[i]);

		var script = document.getElementById(this.defaults.updaterId);
		var head = document.getElementsByTagName('head')[0];
		if (head && script) {
			head.removeChild(script);

			// Schedule the next request (in case it's necessary) so
			// that it won't violate the '1 call/sec' rule.
			setTimeout(function() { AmzInfo.sendUpdateRequest(); },
				   1000);
		}
	},

	updateItem: function(item) {
		var saleselem = document.getElementById('amzinfo-' + item.asin +
							'-rank');
		if (!saleselem)
			return;
		var newranknode = document.createTextNode(item.salesrank);
		
		saleselem.removeChild(saleselem.firstChild);
		saleselem.appendChild(newranknode);

		// image file (reportedly) could be updated.  if so, replace it
		// with the new one.
		var imgelem = document.getElementById('amzinfo-' + item.asin +
						      '-image');
		if (imgelem.src != item.image.url)
			imgelem.src = item.image.url;

		var priceelem = document.getElementById('amzinfo-' + item.asin
							 + '-price');
		if (priceelem) {
			priceelem.removeChild(priceelem.firstChild);

			var pricetxt = item.listprice.amount + '';

			if (item.listprice.currency == 'JPY')
				pricetxt += '円';
			else {
				// XXX: assume it's USD or GBP
				var pricenum = Number(pricetxt);
				var cents = pricenum % 100;
				var dollars = (pricenum - cents) / 100;
				if (item.listprice.currency == 'USD')
					pricetxt = '$';
				else
					pricetxt = '£';
				pricetxt += dollars + '.' + cents;
			}
			pricetxt = ', ' + pricetxt;

			var node = document.createTextNode(pricetxt);
			priceelem.appendChild(node);
		}

		var avrankelem = document.getElementById('amzinfo-' + item.asin
							 + '-avrate');
		var avrankitem = item.averagerating;
		if (avrankitem != null) {
			var newrankurl = this.convertRating(avrankitem);

			if (avrankelem != null)
				avrankelem.firstChild.src = newrankurl;
			else {
				var parent = document.getElementById('amzinfo-'
					+ item.asin + '-avratebox');
				var prenode = document.createTextNode('Amazonおすすめ度: ');
				var imgnode = document.createElement('img');
				imgnode.src = this.convertRating(avrankitem);
				imgnode.alt = avrankitem;
				var postnode = document.createElement('br');

				parent.appendChild(prenode);
				parent.appendChild(imgnode);
				parent.appendChild(postnode);
			}
		}

		var reviewselem = document.getElementById('amzinfo-' +
							  item.asin +
							  '-reviewlist');
		if (reviewselem)
			this.removeDescendants(reviewselem);
		for (var i = 0; i < item.review.length && i < 3; i++) {
			var newreviewhead = document.createElement('dt');
			var newrating = document.createElement('img');
			newrating.src =
				this.convertRating(item.review[i].rating);
			newrating.alt = item.review[i].rating;
			newreviewhead.appendChild(newrating);

			var newreviewdesc = document.createElement('dd');
			var newsummary =
				document.createTextNode(item.review[i].summary);
			newreviewdesc.appendChild(newsummary);

			reviewselem.appendChild(newreviewhead);
			reviewselem.appendChild(newreviewdesc);
		}
	},

	convertRating: function(newrate) {
		var m = newrate.match(/(\d)\.(\d)/);
		var r;

		if (m != null)
			r = m[1] + '-' + m[2];
		else
			r = newrate + '-0';

		return ('http://g-images.amazon.com/images/G/01/detail/stars-' +
			r + '.gif');
	}
};
