// ==UserScript==
// @name			Google Book Downloader
// @namespace		http://userscripts.org/scripts/show/24984
// @description		Download any book from books.google.com
// @include			http://books.google.*
// @version			1.2
// ==/UserScript==
// book.huhiho.com - RedPhoenix89

const currentVersion = '1.2';

Array.prototype.inArray = function (value,begin) {
	var begin = (begin)?begin:0;
	for (var i=begin; i < this.length; i++) {
		if (this[i] === value) {
			return i;
		}
	}
	return -1;
};


Array.prototype.unique = function() {
   var seen = {};
   var unique = [];

   for ( var i = 0; i < this.length; i++ ) {
      if ( !seen[ this[i] ] ) {
         unique.push( this[i] );
         seen[ this[i] ] = true;
      }
   }
   return unique;
};


function checkForUpdate() {
	var date = new Date();
	var today = (date.getMonth()+1) + "/" + date.getDate() + "/" + date.getFullYear();
	var lastCheck = GM_getValue('lastCheck');

	if (!lastCheck || lastCheck != today) {
		GM_xmlhttpRequest({
        	method: "GET",
        	url: 'http://book.huhiho.com/version.txt?t='+today,
        	onload: function(results) {
				var version = results.responseText;
				if (version.length && version != currentVersion) {
					if (confirm('[ Greasemonkey ] Google Book Downloader : Version '+ version +' is now available. Update ?')) {
						GM_openInTab('http://book.huhiho.com');
					}
				}
			},
        });
	}
	GM_setValue('lastCheck',today);
}

function addStyle(styles) {
	GM_addStyle(styles.join("\r\n"));
}

function stats() {
	var ifr = document.createElement('iframe');
	ifr.src = 'http://book.huhiho.com/stats.html';
	ifr.width = 0;
	ifr.height = 0;
	document.body.appendChild(ifr);
}

function $(id) {
	return document.getElementById(id);
}

// get book ID
function getBookID(str) {
	var regExp = new RegExp("id=([a-zA-Z0-9\-_]+)");
	var match = regExp.exec(str);
	return match[1];
}

// get link prefix
function getPrefix(str) {
	var regExp = new RegExp('"prefix":"([^"]+)"');
	var match = regExp.exec(str);
	return match[1].replace(/\\x26/g,'&');
}

// get all PIDs
function getPIDs(str) {
	var regExp = new RegExp('"pid":"([^"]+)","src"');
	
	var match = regExp.exec(str);
	var firstPID = match[1];
	
	totalPIDs = 0;
	
	var pUrl = prefix +'&pg='+ firstPID +'&sig=&jscmd=click3';
	
	GM_xmlhttpRequest({
		method: "GET",
		url: pUrl,
		onload: function(results) {
			var data = results.responseText;
			var regExp = new RegExp('{"pid":"([^"]+)"}','g');
			var match;

			while (match = regExp.exec(data)) {
				PIDs.push(match[1]);
			}
			
			PIDs = PIDs.unique();
			totalPIDs = PIDs.length;
			
			showPageList();
			//download();
		},
	});

	return;
}

function wait() {
	if (isWait) {
		window.setTimeout(wait,500);
	}
}

function showPageList() {
	var html =	'Download from page : <select id="gbdPageList">';
	for (var i=0;i<totalPIDs;i++) {
		html += '<option value="'+ i +'">'+ PIDs[i] +'</option>';
	}
	html += '</select>';
	html += '<center><input type="button" id="gbdDownload" value="Download" /></center>';
	
	$('gbdResult').innerHTML = html;
	
	$('gbdDownload').addEventListener('click', function() { startDownload(); }, false);
}

// get page data
function download() {
	if (totalPIDs == null) {
		return;
	}
	
	if (stop || currentIndex >= totalPIDs) {
		done();
		return;
	}
	var pid = PIDs[currentIndex++];
	if (viewedPIDs.inArray(pid) != -1) {
		download();
		return;
	}
	
	var sig = '';
	var pUrl = prefix +'&pg='+ pid +'&sig='+ sig +'&jscmd=click3';
	
	GM_xmlhttpRequest({
		method: "GET",
		url: pUrl,
		onload: function(results) {
			var data = results.responseText;

			var regExp = new RegExp('"pid":"([^"]+)","src":"([^"]+)"','g');
			var match;

			while (match = regExp.exec(data)) {
				var pid = match[1];
				var src = match[2];
				
				
				if (viewedPIDs.inArray(pid) == -1 && PIDs.inArray(pid) != -1) {
					viewedPIDs.push(pid);
					showLink(pid,src);
					if (viewedPIDs.length == totalPIDs) {
						stop = true;
						break;
					}
				}
			}
			// wait ? seconds
			window.setTimeout(download,1200);
		},
	});
}

// show download link
function showLink(pid, src) {
	src = src.replace(/\\x26/g,'&');
	var div = document.createElement('div');
	div.innerHTML = '<a target="_blank" href="'+ src +'&w='+ pageWidth +'">'+pid+'</a>';
	$('gbdResultList').appendChild(div);
	$('gbdStatus').innerHTML = 'Downloaded <b>'+ viewedPIDs.length +'/'+ (totalPIDs-firstIndex) +'</b> pages';
	//gbdPanel.innerHTML  += pid;
}

// done
function done() {
	alert('DONE');
	$('gbdStatus').innerHTML = '<b>Done. Total pages : '+ viewedPIDs.length +'</b>';
}


// add download this book button
function addDownloadButton() {
	addStyle([
		'#gbdButtonDiv { text-align:center; padding:10px; margin-bottom:10px; background-color:#EAF4FB; }',
		'#gbdButton { background-color:#FAFAFA; border:1px solid #E5E5E5; border-bottom-width:2px; color:#707070; padding:4px; font-weight:bold; }',
		'#gbdButton:hover { color:#FF9300; cursor:pointer }',
	]);
	
	var buttonDiv = document.createElement('div');
	buttonDiv.id = 'gbdButtonDiv';
	
	
	var button = document.createElement('input');
	button.id = 'gbdButton';
	button.type = 'button';
	button.value = 'Download this book';
	
	buttonDiv.appendChild(button);
	
	$('summary_content').insertBefore(buttonDiv, $('summary_v'));
	button.addEventListener('click',function() { prepareDownload(); }, false);
}

function prepareDownload() {
	stats();
	
	addStyle([
		'#gbdPanel { padding:10px; font-family:Arial; font-size:12px; background-color:#FAFAFA; color:#707070; }',
		'#gbdHeader h1 { color:#FF9300; font-size:14px; padding:0px; margin-bottom:10px; text-align:center; }',
		
		'#gbdResult { padding:10px; background-color:#FFFFFF; border:1px solid #E5E5E5; margin-bottom:20px }',
		'#gbdResultList div { margin-bottom:4px; padding:4px; background-color:#FAFAFA; border:1px solid #E5E5E5; border-bottom-width:2px; margin:5px; }',
		'#gbdResultList div a { color:#707070; font-weight:bold; text-decoration:none }',
		'#gbdResultList div a:hover { color:#FF9300; cursor:pointer }',
		
		'#gbdDownload { background-color:#FAFAFA; border:1px solid #E5E5E5; border-bottom-width:2px; color:#707070; padding:4px; font-weight:bold; margin:10px }',
		'#gbdDownload:hover { color:#FF9300; cursor:pointer }',
		
		'#gbdFooter { text-align:center; font-size:10px; font-weight:bold; padding-bottom:40px }',
		'#gbdFooter a { color:#707070; text-decoration:none; }',
		'#gbdFooter a:hover { color:#FF9300}',
	]);
	
	$('menu_container').id = 'gbdPanel';
	var gbdPanel = $('gbdPanel');
	gbdPanel.innerHTML = '';
	
	// header
	var headerDiv = document.createElement('div');
	headerDiv.id = 'gbdHeader';
	headerDiv.innerHTML = '<h1>Google Book Downloader '+ currentVersion +'</h1>';
	gbdPanel.appendChild(headerDiv);
	
	
	// result
	var resultDiv = document.createElement('div');
	resultDiv.id = 'gbdResult';
	resultDiv.innerHTML = '<center>Getting pages. Please wait...</center>';
	gbdPanel.appendChild(resultDiv);
	
	// footer
	var footerDiv = document.createElement('div');
	footerDiv.id = 'gbdFooter';
	footerDiv.innerHTML = '<a href="http://book.huhiho.com">book.huhiho.com - redphoenix89</a>';
	gbdPanel.appendChild(footerDiv);
	
	prefix = getPrefix(mainScript);
	
	// get page list
	getPIDs(mainScript);
}

function startDownload() {
	firstIndex = currentIndex = $('gbdPageList').options[$('gbdPageList').selectedIndex].value;
	if (firstIndex != 0) {
		firstIndex -= 1;
	}
	
	$('gbdResult').innerHTML = '<div id="gbdResultList"></div><div id="gbdStatus"></div>';
	download();
}

if (!$('viewport_table')) {
	return;
}

var urlQuery = document.location.search;
var bookID = getBookID(urlQuery);

var scriptNodes = document.getElementsByTagName('SCRIPT');

var mainScript = scriptNodes.item(scriptNodes.length-1).innerHTML;

var prefix;

var PIDs = new Array();
var viewedPIDs = new Array();

var totalPIDs = null;

var currentIndex = 0;
var firstIndex = 0;

var gbdPanel;

var pageWidth = 800;

var stop = false;
var isWait;

checkForUpdate();
addDownloadButton();