// ==UserScript==
// @name           Facebook Monsters Enhancer
// @namespace      http://userscripts.org/users/49912
// @description    Creates a menu to use those applications in facebook and has auto-play functions
// @source         http://userscripts.org/scripts/show/25396
// @identifier     http://userscripts.org/scripts/source/25396.user.js
// @version        1.0-alpha2
// @date           2008-04-21
// @creator        ViXaY XaVieR and Piotr P. Karwasz
// @include        http://apps.facebook.com/slayers/*
// @include        http://apps.facebook.com/werewolves/*
// @include        http://apps.facebook.com/vampires/*
// @include        http://apps.facebook.com/zombies/*
// ==/UserScript==
/*
The followings notes are in WIKIPAD style for easier export to userscripts meta data page

+++ DISCLAIMER
	This script is an *ALPHA*, so it can work poorly or not at all. Eventually this script could be merged with:
	http://userscripts.org/scripts/show/20462

+++ PURPOSE
	* Organise players in clans that can feed mutually and attack each other
	* Auto feed monsters from the clan to gain money & attacks
	* Auto attack friends to gain experience points
	* Do this all easily and conveniently, without manual effort (i.e. a bot)

+++ FEATURES:
	* Creates a Menu on the right hand side listing all usual functions. _Benefit:_ Saves you valuable time in going about your daily tasks, especially across the different monster types.
	* Creates a statistics pane on bottom left containing stats for all your monster types! convenient one glance stats!
	* Auto-Feed people from history for all your monsters to get money automatically.
		*   Currently 8 feeds allowed/day * 30 bucks/feed = *240/day/monster* * 4 monster types = *960* bucks/day total!!,
		*   This takes time (5 secs + 3 guesstimated secs reload time) * 3 clicks per feed * 8 feeds/day * 4 monsters = 768 secs = *12.8* mins! 
		*   Thus gives you increased # of attacks each day! The script selects people that already fed you and most probably will feed you back: it means 2 attacks/feed
		*   You can leave the page open in a tab all the time and it will automatically do it everyday without your intervention!
	* Auto-Attack monsters less than twice as strong as you.

++++ HOW AUTO-FEED WORKS:
	1. There is an 'Autofeed!' button on the sidebar. If you press the function will activate. (The button will now show 'Manual feed')
	2. On your profile or a feeding related page (event-history, feed-result, ...) the script will begin to work, showing what it's doing on the status line(on top of the sidebar).

Current Logic for feeding:
	Read your feeding history to populate your clan. Than attack the 8 people that fed you last.
	Switch to the next monster when it's done

++++ HOW AUTO-ATTACK WORKS:
	1. There is an 'Autoattack!' button on the sidebar. If you press it the function will activate. (The button will now show 'Manual attack')
	2. On your profile or an attacking related page (fighting-main, fighting-confirm, ...) the script will begin to work, showing what it's doing on the status line (on top of the sidebar).

Current Logic for attacking:
	Go from top to bottom, choose an opponent who is less than twice as strong as you.
	Use all 3 attacks per round and than choose another defender monster type randomly
	Once done switch to another monster type.

++++ STATISTICS PANE
	* Gets updated as you move around the different pages
	* It should give reliable information, but it's not guaranteed at the beginning
	* Is there just for quick reference
	* You have to visit your main profile page to get the total amount of money you have in your account

+++ NOTES:
Tested with Firefox 2.0.0.11+ & Greasemonkey 0.7.20070607.0+
http://userscripts.org/scripts/show/20462
To help debug problems please check the Tools->Error Console and post messages from the error & messages tabs to the comments  section.

http://userscripts.org/scripts/show/20462
this is the magic boon i bestow upon you to grow powerful quicker than your peers. After many years of meditation was i able to craft such a delicate spell to aid you in battle, use it wisely!

+++ CREDITS
Facebook Slayers/Werewolves/Vampires/Zombies Enhancer by ViXaY Xavier (http://userscripts.org/users/42874) for the initial code

+++ CHANGELOG
	* v1.0-alpha First alpha release
		
+++ KNOWN BUGS
	
+++ TO DO
	- Show who are the people in the clan
*/

(function () {

// bit masks
var PREF_RESET = 0;
var PREF_AUTOFEED = 1;
var PREF_AUTOATTACK = 2;
var CLANSELECT_MANUAL = 4;
var ALREADY_GOING = 8;
var PREF_ALL = 255;

// configurable constants
var SCRIPT = {
	name: "Facebook Monsters Enhancer",
	namespace: "http://userscripts.org/users/49912",
	description: 'Creates a menu to use those applications in facebook and has auto-play functions',
	source: "http://userscripts.org"// script homepage/description URL
			+ "/scripts/show/25396",
	identifier: "http://userscripts.org"	// script URL
			+ "/scripts/source/25396.user.js",
	version: "1.0-alpha2", // version
	date: (new Date(2008, 4 - 1, 21)) // update date
			.valueOf()
};
var CLAN_MIN_DIM = 8; // minimal dimension of your clan
var CLAN_MAX_DIM = 16; //maximal dimension of your clan
var APP_NAME = "Facebook Monsters Enhancer";

// non-configurable constants
var MONSTER_TYPE = ["slayer", "werewolf", "vampire", "zombie", "slayers", "werewolves", "vampires", "zombies"];
var SLAYER = 0;
var WEREWOLF = 1;
var VAMPIRE = 2;
var ZOMBIE = 3;
var NR_MONSTERS = 4;
var PLURAL = NR_MONSTERS;
var APPS_URL = "http://apps.facebook.com/"
var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');


// global variables
// variables that need saving
var mstatus;
var auto_timer; // default countdown value for timer
var monsters = new Array();

// variables that are session only
var current_type = "";
var current_page = "";
var current_params = "";
var divs;
var next_attack, next_attack_type;
var next_feed, next_feed_type;
// Milliseconds give integer overflow when storing
var now = new Date().getTime();
now = (now - (now % 1000)) / 1000;
// what to do when timer goes out
var gnext_page; // where to go, can be a string (URL) or an element (button to press)
var ginterval; // to store the periodic timer function
var gcountdown; // how long that function waits
var gmessage; // status message to show


// update automatically
try {
	addEventHandler(window, "load", function () { try {
		(unsafeWindow || window.wrappedJSObject || window)
				.UserScriptUpdates.requestAutomaticUpdates(SCRIPT);
		} catch	(ex) {} }, false);
} catch	(ex) {}

// objects
function ClanMember(mtype) {
	this.id = 0;
	this.type = mtype;
	this.last_fedback = 0;
	this.next_feed = 0;
}

function Monster(mtype) {
	this.type = mtype;
	this.power = GM_getValue(mtype + "/power",0);
	this.next_feed = parseInt(GM_getValue(mtype + "/next_feed",0));
	this.last_feed = new Array();
	this.feeds_left = 0;
	for (var i = 0; i < 8; i++) {
	this.last_feed[i] = parseInt(GM_getValue(mtype + "/last_feed/" + i,0));
	if (this.last_feed[i] < (now - 22 * 60 * 60)) { 
	    this.feeds_left++;
	     }
	}
	//GM_log(this.type + " restoring: " + this.next_feed);
	this.attacks_left = GM_getValue(mtype + "/attacks_left",-1);
	this.next_attack = GM_getValue(mtype + "/next_attack",0);
	this.money = GM_getValue(mtype + "/money",0);
	this.clan_size = GM_getValue(mtype + "/clan_size",0);
	this.clan = new Array();
	
	for (var i=0; i < this.clan_size; i++) {
		var clanmember = new ClanMember(mtype);
		clanmember.id = parseInt(GM_getValue(mtype + "/clan/" + i + "/id"));
		clanmember.last_fedback = GM_getValue(mtype + "/clan/" + i + "/last_fedback");
		clanmember.next_feed = GM_getValue(mtype + "/clan/" + i + "/next_feed");
		this.clan.push(clanmember);
	}
	
	// methods
	this.save = monsterSave;
	this.feed = monsterFeed;
	this.attack = monsterAttack;
	this.selectClanMember = monsterSelectClanMember;
	this.showProfile = monsterShowProfile;
	this.historyAnalyse = monsterHistoryAnalyse;
	this.selectLeastClanMember = monsterSelectLeastClanMember;
	this.addOrReplaceClanMember = monsterAddOrReplaceClanMember;
}

// Adds the clanmember or replaces the worst clanmember with the new
// Returns the index of the elements inserted/replaced or -1 otherwise.
function monsterAddOrReplaceClanMember (clanm) {
    if (this.clan_size >= CLAN_MAX_DIM) {
	var replace_index;
	replace_index = this.selectLeastClanMember();
	if (replace_index == undefined) alert("Something strange happened");
	if (this.clan[replace_index].last_fedback < clanm.last_fedback) {
	    this.clan[replace_index] = clanm;
	    clan_ids[replace_index] = id;
	    GM_log("Adding " + clanm.id);
	    return replace_index;
	} else {
	    // if this clanmember is even worse, don't bother replacing
	    return -1;
	}
    } else {
	GM_log("No limit adding " + clanm.id);
	this.clan.push(clanm);
	this.clan_size++;
	return (this.clan_size - 1);
    }
}

function monsterHistoryAnalyse() {
    var id;
    var clan_ids = new Array();
    var num = new RegExp('\\d+');

    // populating the array with clan member ids
    for (var i = 0; i < this.clan_size; i++ ) {
	clan_ids.push(this.clan[i].id);
    }

    divs = getElementsByClassName("list_action_call","span");
    var pnode = divs[0].parentNode.parentNode;
    for (var i = 0; i < divs.length; i++) {
	id = parseInt(divs[i].getElementsByTagName('a')[0].href.match(num));
	var str = divs[i].parentNode.getElementsByTagName('span')[1].innerHTML + ", " + new Date().getFullYear() + " 00:00:00";
	var feed_date = new Date(str).getTime();
	feed_date = (feed_date - (feed_date % 1000)) / 1000;

	var ind = clan_ids.indexOf(id);
	if (ind != -1) {
	    pnode.removeChild(divs[i].parentNode);
	    // Update last_fedback of the monster
	    if (this.clan[ind].last_fedback < feed_date) {
		this.clan[ind].last_fedback = feed_date;
	    }
	} else {
	    var clanm = new ClanMember(this.type);
	    clanm.id = id;
	    clanm.last_fedback = feed_date;
	    ind = this.addOrReplaceClanMember(clanm);
	    if (ind != -1) {
		// We added someone
		clan_ids[ind] = id;
		GM_log("Adding to clan_ids: " + ind + ", value " + clan_ids[ind]);
	    }
	}
    }
}

function monsterSave() {
    GM_setValue(this.type + "/power", this.power);
    GM_setValue(this.type + "/next_feed", this.next_feed);
    for (var i = 0; i < 8; i++) {
	GM_setValue(this.type + "/last_feed/" + i, this.last_feed[i]);
    }
    //GM_log(this.type + " saving: " + this.next_feed);
    GM_setValue(this.type + "/attacks_left", this.attacks_left);
    GM_setValue(this.type + "/next_attack", this.next_attack);
    GM_setValue(this.type + "/money", this.money);
    GM_setValue(this.type + "/clan_size", this.clan.length);
    for (var i=0; i < this.clan.length; i++) {
//	GM_log(this.type + " id " + this.clan[i].id + " fb " + this.clan[i].last_fedback + " nf " + this.clan[i].next_feed);
        GM_setValue(this.type + "/clan/" + i + "/id", this.clan[i].id);
        GM_setValue(this.type + "/clan/" + i + "/last_fedback", this.clan[i].last_fedback);
        GM_setValue(this.type + "/clan/" + i + "/next_feed", this.clan[i].next_feed);
    }
}

// Returns the clanmember that can be already fed and fed you back most recently
// or undefined if an error occured
function monsterSelectClanMember() {
    var last_fedback = -1;
    var clanmember = undefined;
    for (var i = 0; i < this.clan_size; i++) {
	if ((this.clan[i].next_feed < now) && (this.clan[i].last_fedback > last_fedback)) {
	    last_fedback = this.clan[i].last_fedback;
	    clanmember = this.clan[i];
	}
    }
    return clanmember;
}

// Feeds the monster 'id'
function monsterFeed(id) {
    gmessage = "Feeding a " + MONSTER_TYPE[this.type] + "...";
    gcountdown = auto_timer; // set timer to default
    gnext_page = APPS_URL + MONSTER_TYPE[this.type + NR_MONSTERS] + "/feed-main.php?consumer_id=" + id;
}

function monsterAttack(id) {
}

function monsterShowProfile() {
    gmessage = "Going to " + MONSTER_TYPE[this.type + NR_MONSTERS] + " profile...";
    gcountdown = auto_timer;
    gnext_page = APPS_URL + MONSTER_TYPE[this.type + NR_MONSTERS] + "/side-nav.php?ref=top_nav";
}

function monsterSelectLeastClanMember() {
    // give the index in the Array of the least active clanMember;
    var lf = now;
    var index = undefined;
    for (var i = 0; i < this.clan_size; i++ ) {
	if (this.clan[i].last_fedback < lf) {
	    lf = this.clan[i].last_fedback;
	    index = i;
	}
    }
    return index;
}

function parseURL (url) {
	var tmp = url.split('/')[3];
	current_type = MONSTER_TYPE.indexOf(tmp) - NR_MONSTERS;
	tmp = url.split('/')[4];
	current_page = tmp.split('?')[0];
	current_params = tmp.split('?')[1];
	if (current_params == undefined) {
	    current_params = '';
	}
}


// ================ Setup Menu ==================
function insertMenu() {

	document.title = document.title + " enhanced by VX";

	var menuCode = []; // temporary array to store strings for concatenation
	//type_ind <= 0 ? 3 : type_ind - 1; //code to auto select a monster type
	// create the code for the menu
	menuCode.push('<div class="monsterHeading">-' + MONSTER_TYPE[current_type].toUpperCase() + '-</div>');
	menuCode.push('Status:<br /><span id="monsteraction"></span><br /><span id="monstertimer"></span>');
	menuCode.push('<div class="monsterSection">-Battles-</div>');
	menuCode.push(createLink("fighting-main","monster_type=" + MONSTER_TYPE[current_type],"Fight!")+ '<br />' );
	
	for (var i=0; i < NR_MONSTERS; i++) {
	menuCode.push(createLink("fighting-main","monster_type=" + MONSTER_TYPE[i],"Fight " + MONSTER_TYPE[PLURAL + i])+ '<br />');
	}
	
	menuCode.push('<div class="monsterSection">-Get Money-</div>');
	menuCode.push(createLink("feed-home","","Feed!")+ '<br />');
	menuCode.push(createLink("Bite")+ '<br />');
//	menuCode.push('<div class="monsterSection">-Stats-</div>');
//	menuCode.push(createLink("side-nav","ref=top_menu","My " + MONSTER_TYPE[current_type])+ '<br />');
//	menuCode.push(createLink("fighting-history","","My Fight History") + '<br />');
//	menuCode.push(createLink("event-history","","My Feed History") + '<br />');
//	menuCode.push(createLink("friend-rank","ref=top_menu","My Friend Rank")+ '<br />');
//	menuCode.push(createLink("global-rank","ref=top_menu","My Global Rank")+ '<br />');
//	menuCode.push('<div class="monsterSection">-My Monsters-</div>');
//	
//	for (var i=0; i < NR_MONSTERS; i++) {
//	menuCode.push(createLink("side-nav","ref=top_nav","My " + MONSTER_TYPE[i], APPS_URL + MONSTER_TYPE[PLURAL + i] + '/')+ '<br />');
//	}
//	
	menuCode.push('<div class="monsterSection">-Items-</div>');
	menuCode.push(createLink("store-main","ref=top_menu","Store")+ '<br />');
	menuCode.push('<div class="monsterSection">-Social-</div>');
	menuCode.push(createLink("Blog")+ '<br />');
	menuCode.push(createLink("Forum")+ '<br />');
	menuCode.push('<div class="monsterSection">-Misc-</div>');
	menuCode.push(createLink("refresh-profile","","Refresh Profile")+ '<br />');
	menuCode.push(createLink("Help")+ '<br />');
	menuCode.push('Same Page in: <br />');
	
	for (var i=0; i < NR_MONSTERS; i++) {
	menuCode.push(createLink("","","&nbsp;&nbsp;" + MONSTER_TYPE[i], APPS_URL + MONSTER_TYPE[PLURAL + i] + '/' + current_page + '?' + current_params)+ '<br />');
	}
	
	menuCode.push('<button id="autofight" type="button">' + (mstatus & PREF_AUTOATTACK ? "Manual " : "Auto") + 'attack!</button><br />');
	menuCode.push('<button id="autofeed" type="button">' + (mstatus & PREF_AUTOFEED ? "Manual " : "Auto") + 'feed!</button><br />');
	
	var menu = document.createElement('div');
	menu.id = 'FBMonstersMenu';
	menu.innerHTML = menuCode.join(''); // concatenate the string efficiently (faster than +)
	// see http://aymanh.com/9-javascript-tips-you-may-not-know for more information
	menuCode.length = 0; //Reset/Empty the array

	menuCode.push("#FBMonstersMenu { position:fixed; top:2px; right:2px; border:2px solid #6D84B4; background:#EEEEEE; color:#3B5998; padding:2px; font-weight:bold; }");
	menuCode.push("#FBMonstersMenu div.monsterSection { text-align:center; padding-top:2px; }");
	menuCode.push("#FBMonstersMenu div.monsterHeading { text-align:center; background: #6D84B4; color: #FFFFFF; }");
	menuCode.push("#FBMonstersMenu a { color: #BB0011; text-decoration:none; }");
	menuCode.push("#FBMonstersMenu a:hover { color:#B22222; text-decoration:underline; }");
	
	var style = document.createElement('style');
	style.type = "text/css";
	style.innerHTML = menuCode.join(''); 
	menuCode.length = 0; //Reset/Empty the array
	
	// Insert the menu code and style into the document
	try {
		document.getElementsByTagName('head')[0].appendChild(style);
	} catch (ex) {}
	document.body.insertBefore(menu, document.body.lastChild);

// ================ Setup Statistics ==================
	menuCode.push('<div class="monsterHeading">-STATISTICS-</div>');
	menuCode.push('<table>');
	//insert the last time we cleared the flags as tooltips for the headers
	var dateformat = "MMM d, y HH:mm";
	menuCode.push('<tr><th><b>M</b></th><th><b>Points</b></th><th><b>Bucks</b></th><th><b title="'+
			formatDate(monsters[current_type].next_attack,dateformat) + '">Fights</b></th><th><b title="'+
			formatDate(monsters[current_type].next_feed,dateformat) + '">Feeds</b></th></tr>');
	for (var i=0; i < NR_MONSTERS; i++) {
		menuCode.push('<tr>');
		//1st cell - monster type
		menuCode.push('<td>' + MONSTER_TYPE[monsters[i].type].charAt(0).toUpperCase() +'</td>');
		//2nd cell - monster power
		menuCode.push('<td id="' + MONSTER_TYPE[i] + '/power">' + monsters[i].power + "</td>");
		//3th cell - monster money
		menuCode.push('<td id="' + MONSTER_TYPE[i] + '/money">' + monsters[i].money + "</td>");
		//4th cell - monster attacks_left
		menuCode.push('<td id="' + MONSTER_TYPE[i] + '/attacks_left">' + (monsters[i].attacks_left == -1 ? '?' : monsters[i].attacks_left )+ "</td>");
		//5th cell - monster feeds_left
		menuCode.push('<td id="' + MONSTER_TYPE[i] + '/feeds_left">' + monsters[i].feeds_left + "</td>");
		menuCode.push('</tr>');
	}

	menuCode.push('<tr> <td colspan="0" title="'+formatDate(1000*next_attack,dateformat) + '"> ');
	if (next_attack > now) {
	    menuCode.push('Next fight in ' + secondsToString(next_attack - now) + ' (' +
			MONSTER_TYPE[next_attack_type] + '). </td></tr>');
	} else {
	    menuCode.push('Next fight: NOW!');
	}
	menuCode.push('<tr> <td colspan="0" title="'+formatDate(1000*next_feed,dateformat) +'"> ');
	if (next_feed > now) {
	    menuCode.push('Next feed in ' + secondsToString(next_feed - now) + ' (' +
			MONSTER_TYPE[next_feed_type] + '). </td></tr>');
	} else {
	    menuCode.push('Next feed: NOW!');
	}
	menuCode.push('</table>');
	menuCode.push('<a id="refreshStats">Gather Data</a>');
	
	menu = document.createElement('div');
	menu.id = 'FBStats';
	menu.innerHTML = menuCode.join(''); // concatenate the string efficiently (faster than +)
	// see http://aymanh.com/9-javascript-tips-you-may-not-know for more information
	menuCode.length = 0; //Reset/Empty the array
	
	menuCode.push("#FBStats { position:fixed; bottom:2px; left:2px; border:2px solid #6D84B4; background:#EEEEEE; color:#3B5998; padding:2px; font-weight:bold; }");
	menuCode.push("#FBStats div.monsterSection { text-align:center; padding-top:2px; }");
	menuCode.push("#FBStats div.monsterHeading { text-align:center; background: #6D84B4; color: #FFFFFF; }");
	menuCode.push("#FBStats a { color: #BB0011; text-decoration:none; }");
	menuCode.push("#FBStats a:hover { color:#B22222; text-decoration:underline; }");
	menuCode.push("#FBStats table { border-spacing: 0px; }");
	menuCode.push("#FBStats table th { border-width: 1px 1px 1px 1px; padding: 2px 2px 2px 2px; border-style: solid solid solid solid; }");
	menuCode.push("#FBStats table td { border-width: 1px 1px 1px 1px; padding: 2px 2px 2px 2px; border-style: solid solid solid solid; }");
			
	style = document.createElement('style');
	style.type = "text/css";
	style.innerHTML = menuCode.join(''); 
	menuCode.length = 0; //Reset/Empty the array
	
	// Insert the menu code and style into the document
	try {
		document.getElementsByTagName('head')[0].appendChild(style);
	} catch(e) {}
	document.body.insertBefore(menu, document.body.lastChild);
	
	// add an even listeners
	var t_elm = document.getElementById('autofight');
	t_elm.addEventListener('click',toggleAutoattack,true);
	t_elm = document.getElementById('autofeed')
	t_elm.addEventListener('click',toggleAutofeed,true);
	
	
	//recheck the checkboxes from persistent variables
}

// ================ Utility functions ==================
function createLink(sPage, sParams, sTitle, sURL) {
	sTitle = sTitle || sPage; // default title = Page name unless it's provided
	sURL = sURL || APPS_URL + MONSTER_TYPE[PLURAL + current_type] + '/'; // default to current app url
	var sExt = '.php';
	if (sPage == undefined || sPage == "") sExt = '';

	if (sParams == undefined || sParams == "") {
		return '<a href="' + sURL + sPage.toLowerCase() + sExt + '">' + sTitle + '</a>';
	} else {
			sParams = '?' + sParams;
			return '<a href="' + sURL + sPage.toLowerCase() + sExt + sParams + '">' + sTitle + '</a>';
	}
}

// Returns null if expr didn't match anything
function getFirstXPathResult(expr, node)
{
	if (!node) node = document;
	var res = document.evaluate(expr, node, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
	return res.singleNodeValue;
}

//http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
function getElementsByClassName(className, tag, elm){
	var testClass = new RegExp("(^|\\\\s)" + className + "(\\\\s|$)");
	tag = tag || "*";
	elm = elm || document;
	var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
	var returnElements = [];
	var current;
	var length = elements.length;
	for(var i=0; i<length; i++){
		current = elements[i];
		if(testClass.test(current.className)){
			returnElements.push(current);
		}
	}
	return returnElements;
}

//http://www.webmasterworld.com/javascript/3214735.htm
// use for the new scheme they have in facebook divs naming
function getElementsByIDPattern(inPattern,inRoot){
	var elem_array = new Array;
	if(typeof inRoot.firstChild!= 'undefined'){
		var elem = inRoot.firstChild;
		while (elem!= null){
			if(typeof elem.firstChild!= 'undefined'){
				elem_array = elem_array.concat(getElementsByIDPattern(inPattern,elem));
			}
			if(typeof elem.id!= 'undefined'){
				var reg = new RegExp('^'+inPattern+'$');
				if(elem.id.match(reg)){
					elem_array.push(elem);
				}
			}
			elem = elem.nextSibling;
		}
	}
	return elem_array;
}

//ASSERTION FUNCTIONS
//http://aymanh.com/9-javascript-tips-you-may-not-know
function assertException(message) { this.message = message; }

assertException.prototype.toString = function () {
	return 'AssertException: ' + this.message;
};

function assert(exp, message) {
	if (!exp) {
		throw new AssertException(message);
	}
}

function LZ(x) {return(x<0||x>9?"":"0")+x;}

//http://www.mattkruse.com/javascript/date/source.html
// ------------------------------------------------------------------
// formatDate (date_object, format)
// Returns a date in the output format specified.
// The format string uses the same abbreviations as in getDateFromFormat()
// ------------------------------------------------------------------
function formatDate(date,format) {
	format=format+"";
	date = new Date(date);
	var result="";
	var i_format=0;
	var c="";
	var token="";
	var y=date.getYear()+"";
	var M=date.getMonth()+1;
	var d=date.getDate();
	var E=date.getDay();
	var H=date.getHours();
	var m=date.getMinutes();
	var s=date.getSeconds();
	var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,KK,K,kk,k;
	// Convert real date parts into formatted versions
	var value=new Object();
	if (y.length < 4) {y=""+(y-0+1900);}
	value["y"]=""+y;
	value["yyyy"]=y;
	value["yy"]=y.substring(2,4);
	value["M"]=M;
	value["MM"]=LZ(M);
	value["MMM"]=MONTH_NAMES[M-1];
	value["NNN"]=MONTH_NAMES[M+11];
	value["d"]=d;
	value["dd"]=LZ(d);
	value["E"]=DAY_NAMES[E+7];
	value["EE"]=DAY_NAMES[E];
	value["H"]=H;
	value["HH"]=LZ(H);
	if (H==0){value["h"]=12;}
	else if (H>12){value["h"]=H-12;}
	else {value["h"]=H;}
	value["hh"]=LZ(value["h"]);
	if (H>11){value["K"]=H-12;} else {value["K"]=H;}
	value["k"]=H+1;
	value["KK"]=LZ(value["K"]);
	value["kk"]=LZ(value["k"]);
	if (H > 11) { value["a"]="PM"; }
	else { value["a"]="AM"; }
	value["m"]=m;
	value["mm"]=LZ(m);
	value["s"]=s;
	value["ss"]=LZ(s);
	while (i_format < format.length) {
		c=format.charAt(i_format);
		token="";
		while ((format.charAt(i_format)==c) && (i_format < format.length)) {
			token += format.charAt(i_format++);
			}
		if (value[token] != null) { result=result + value[token]; }
		else { result=result + token; }
		}
	return result;
}

// Takes a Time in string (3 horus 23 minutes..etc) and converts it to seconds
function getSecondsFromString(sMsg) {
	var re = /\s(\d+)\s+hour.*\s(\d+)\s+minute.*/;
	var m_result = re.exec(sMsg); //Execute regex on input string
	if (m_result == undefined) return 0;
	if (m_result.length <= 1) return 0;
	var hours = m_result[1];
	var minutes = m_result[2];
	var seconds = /\s(\d+)\ssecond.*/;
	seconds = seconds.exec(sMsg);//Execute regex on input string
	if (seconds == undefined || seconds.length<2) {
		seconds = 0;
  } else {
    seconds = seconds[1];
  }
	return (parseInt(hours,10)*3600 + parseInt(minutes,10)*60 + parseInt(seconds,10));
}

// returns first submit button found on page
function findSubmitButton() {
	// find the right button - for interval to auto click
	var elms = document.getElementsByTagName('input');
	for (i=0; i<elms.length; i++) {
		if (elms[i].type == 'submit') {
			return elms[i];
			break;
		}
	}
	return;
}

// returns a comma seperated number without commas
function getNumber(sText,suffixPattern) {
	var matchResults;
	suffixPattern = suffixPattern || "\\s.*\\spoints.*";
	var tmpRegex = new RegExp("(\\d+(,|\\d)*)" + suffixPattern,"i");
	try {
		matchResults = sText.match(tmpRegex);
		//GM_log("getNumber results:" + matchResults);
		matchResults[1] = matchResults[1].replace(/,/g,""); // clean up commas to get correct conversion to integer
		return parseInt(matchResults[1],10);
	} catch(x) {
		return;
	}
}

// Change the default auto-timer value used for countdowns
function changeTimer() {
	var entry = prompt('Enter a delay in seconds between 1 and 30:',auto_timer);
	if (entry != null) {
		//statements to execute with the value
		if ((entry >= 1) && (entry <= 30)) {
			GM_setValue("timer",entry);
			auto_timer = entry;
		}
	}
}

function secondsToString(sec) {
	var str = '';
	var tmp;
	str = (sec % 60) + " s"; //+ //((sec % 60) == 1 ? "" : "s");
	sec = (sec - (sec % 60)) / 60;
	if (sec) {
		str = (sec % 60) + " m " + str;//((sec % 60) == 1 ? "" : "s") + " " + str;
		sec = (sec - (sec % 60)) / 60;
		if (sec) {
			str = (sec % 60) + " h " + str;//((sec % 60) == 1 ? "" : "s") + " " + str;
		}
	}
	return str;
} 

// to take action if auto is enabled and start the timer interval 
function startActionTimer() {
	
	document.getElementById('monsteraction').innerHTML = gmessage;
	// create annonymous function to call every second to decrement counter
	// and click when counter = 0
	// Interval function that runs every second and checks the countdown timers
	// and takes appropriate action depending on which page we are on
	ginterval = setInterval(function (){
		//GM_log("intervalCheck()"); //DEBUG
		gcountdown--;
		if (gcountdown<=0) {
		document.getElementById('monstertimer').innerHTML = 'NOW!';
		// like use the attack again link instead of visiting the main page
			if (typeof gnext_page == "object") {
				if (!(mstatus & ALREADY_GOING)) {
				    //alert("Pressing button");
				    gnext_page.click();
				    mstatus |= ALREADY_GOING;
				}
			} else {
				if (!(mstatus & ALREADY_GOING)) {
				    //alert("Going to..." + gnext_page);
				    location.href = gnext_page;
				    mstatus |= ALREADY_GOING;
				}
			}
		} else {
			document.getElementById('monstertimer').innerHTML = 'in ' + secondsToString(gcountdown);
		}
	}, 1000);
}

function checkErrorMessage(auto_mode) {
	//Error Checking for:
	// - A TIMEOUT Error (NOT WORKING YET)
	// - CANNOT FEED MORE ERROR (WORKS)
	// - THIS MONSTER IS FULL FOR TODAY (TODO)
	
	// check if achieved quota already
	var errorHeader;
	var errorPage = getElementsByClassName("no_icon","h2");

	// based on mode, get the appropriate value into errorHeader, might be easier to understand in if statement form
	try {
		if (auto_mode == "feed") {
			errorHeader = document.getElementById('error');
		} else if (auto_mode == "attack") {
			errorHeader = getElementsByClassName("status", "h1")[0];
		}
	} catch(x){}
	// check for div id=error_message
	// hit try again if error_message page.
//	if (errorPage != undefined && errorPage.length >= 1) {
//		if (errorPage[0].innerHTML.toLowerCase().indexOf('error while loading page from') != -1)
//		{
//			GM_log("error page encountered");
//			GM_log("Setting reload in 3 seconds");
//			//getElementById("try_again_button").click();
//			//window.location.reload();
//			try {
//				setTimeout(function() {document.getElementById("try_again_button").click();},6000);
//			} catch (x) {
//			}
//			return 0;
//		}
//	}
	if (errorHeader == undefined) { //if no error
		return 0;
	}
	// if we reach here that means that the error header message exists!
	errorHeader = errorHeader.innerHTML.toLowerCase();
	if (errorHeader.indexOf('hours')!=-1 || errorHeader.indexOf('tomorrow') != -1) {
	    var wait;
	    if (errorHeader.indexOf('hours')!=-1) {
	    // Add 1 minute due to rounding error in the string
		wait = getSecondsFromString(errorHeader) + 60;
	    } else {
		wait = 24 * 60 * 60 // Monster full...
	    }
	    if ((errorHeader.indexOf('this') != -1) || (errorHeader.indexOf('tomorrow') != -1)) {
	        // Timeout for this monster
	        var re = /consumer_id=(\d+)/;
		var id = current_params.match(re)[1];
		var clanm;
		if (clanm = getClanMemberByID(id)) {
		    clanm.next_feed = now + wait;
		} else {
		    clanm = new ClanMember(current_type);
		    clanm.id = id;
		    clanm.next_feed = now + wait;
		    monsters[current_type].addOrReplaceClanMember(clanm);
		}

		if (clanm = monsters[current_type].selectClanMember()) {
		    monsters[current_type].feed(clanm.id);
		    gmessage = "Already fed this one,<br /> feeding another...";
		    return 1;
		} else {
		    monsters[current_type].showProfile();
		    gmessage = "Already fed this one,<br /> going to profile...";
		    return 1;
		}
	    // Monster was too much fed today
	    } else {
	    //alert("Increasing next_feed");
	    if (auto_mode == 'feed') {
		monsters[current_type].next_feed = now + wait;
		// Correct the last_feed entries that are erroneous (they say we have still feeds left)
		for (var i = 0; i < 8; i++ )  {
		    if (monsters[current_type].last_feed[i] < (now + wait - 22 * 60 * 60)) {
			monsters[current_type].last_feed[i] = now + wait - 22 * 60 * 60;
		    }
		}
	    } else {
	    monsters[current_type].next_attack = now + wait;
	    monsters[current_type].attacks_left = 0;
	    }
	    monsters[current_type].showProfile();
	    gmessage = "Daily limit reached,<br />going to profile..."; 
	    return 1;
	    }
	} else { // this case shouldn't occur, will occur on feed pages
		GM_log("this case shouldn't occur");
		auto_timer = GM_getValue("timer",5);
	}
}

//code to add checkboxes to select users to feed
function friendsAddCheckBoxes(xpathExpr, checkClass) {
	// ****add checkboxes to the document
	var thisDiv;
	var retValue = '';
	var xResults;
	
	if (xpathExpr == undefined || checkClass == undefined) return;
	// using the xPath method (which is supposed to giver results faster!)
	xResults = document.evaluate(xpathExpr, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	for (var i = 0; i < xResults.snapshotLength; i++) {
		thisDiv = xResults.snapshotItem(i);
		var newcbox = document.createElement('div');
		newcbox.innerHTML ='<input type="checkbox" class="'+checkClass+'" name="' + thisDiv.getElementsByTagName("a")[0].innerHTML + '" title="'+ thisDiv.getElementsByTagName("a")[0].href +'" />';
		//newcbox.innerHTML ='<input type="checkbox" class="SelectFeed" />';
		//GM_log(thisDiv.getElementsByTagName("a")[0].text);
		//GM_log(newcbox.innerHTML);//DEBUG
		thisDiv.appendChild(newcbox); // only appendChild seems to work, insertBefore doesn't! it looks ugly now, need a way to make it appear in a better way
	}
	//thisDiv.insertBefore(newcbox,thisDiv.getElementsByTagName("a")); //insert the checkbox
	//document.insertBefore(newcbox,thisDiv.getElementsByTagName("a")[0]); //insert the checkbox
	//newcbox.addEventListener('click',selectListen,true); // add listener for all the checkboxes
	// ****add listeners for the checkboxes
	xResults = document.evaluate("//input[@class='"+checkClass+"']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var i = 0; i < xResults.snapshotLength; i++) {
		newcbox = xResults.snapshotItem(i);
		//recheck the box if it was checked before
		newcbox.checked = getPersistentVar(newcbox.name,false);
		newcbox.addEventListener('click',selectListen,true); // add listener for all the checkboxes
		//GM_log('adding event listener');//DEBUG
		if (newcbox.checked) retValue = newcbox.title; //save the next url we'll visit (the last checked box)
	}
	return retValue;
}

function historyAddCheckboxes () {
}

// Save Power and money
function getMonsterStats () {
	var iBucks;
	//avoid updating stats when visiting pages not ours
	if (current_params.indexOf("ref=top_nav") != -1 || current_params.length <= 25) {
		try {
			iBucks = getNumber(document.getElementsByTagName("sup")[0].parentNode.innerHTML,"\\s.*\\sbucks.*");
			//GM_log("bucks:"+iBucks);//DEBUG
			monsters[current_type].money = iBucks;
		} catch(x){
			iBucks = '';
		}
		// try getting the points
		try {
			iBucks = getNumber(getElementsByClassName("centered_text emphasis", "td")[0].innerHTML,".*");
			//GM_log('points'+iBucks);//DEBUG
			monsters[current_type].power = iBucks;
		 }catch(x){
			iBucks = '';
		}
	}
}

function toggleAutoattack() {
    if (mstatus & PREF_AUTOATTACK) {
	document.getElementById('autofight').innerHTML = "Autoattack!";
    } else {
	document.getElementById('autofight').innerHTML = "Manual attack!";
    }
    mstatus ^= PREF_AUTOATTACK;
    GM_setValue('status',mstatus);
    clearInterval(ginterval);
    location.reload()
}

function toggleAutofeed() {
    var mstatus = GM_getValue('status');
    if (mstatus & PREF_AUTOFEED) {
	document.getElementById('autofeed').innerHTML = "Autofeed!";
    } else {
	document.getElementById('autofeed').innerHTML = "Manual feed!";
    }
    mstatus ^= PREF_AUTOFEED;
    GM_setValue('status',mstatus);
    clearInterval(ginterval);
    location.reload();
}

function getAttackStats() {
	    var attackPattern = new RegExp("\\[.*\\s(\\d+)\\s+attacks\\sleft\\stoday.*\\]","i"); // detect number of attacks
	    var attacks_left;
	    try {
		attacks_left = parseInt(getElementsByIDPattern(".*main_sub_title",document.body)[0].innerHTML.match(attackPattern)[1],10);
		monsters[current_type].attacks_left = attacks_left;
	    } catch(x) {
		GM_log("error in attacks_left: " + attacks_left);//DEBUG
	    }
	    
	    var attack_power;
	    var divattacker = document.getElementsByTagName("td");
	    try {
		attack_power = getNumber(getElementsByClassName("small_avatar_experience", "div", divattacker[0])[0].innerHTML);
		monsters[current_type].power = attack_power;
	    } catch (x) {
		GM_log("error in attackerPoints: " + attackerPoints);//DEBUG
	    }
}

function selectDefender () {
    var divdefender = document.getElementsByTagName("td");
    if (divdefender !=	undefined && divdefender.length >= 3) {
	divs = getElementsByClassName("small_avatar_experience", "div", divdefender[2]);
	var divsurl = getElementsByClassName("small_avatar_attack_link", "div", divdefender[2]);
	if (divs != undefined && divs.length >= 1) {
	    defenders_power = new Array(divs.length);
	    for (var i = 0; i < divs.length; i++) {
		var temparray = new Array(2);
		// save points
		temparray[0] = getNumber(divs[i].innerHTML);
		// save url
		temparray[1] = divsurl[i].getElementsByTagName("a")[0].href;
		defenders_power[i] = temparray;
		if (canAttack(monsters[current_type].power,temparray[0])) {
		    gnext_page = temparray[1];
		    gmessage = "Choosing defender...";
		    gcountdown = auto_timer;
		    break;
		}
	    }
	}
    }
}	

function canAttack(attackerP, defenderP) {
    var diff = defenderP - attackerP;
    var percent = diff/attackerP*100;
    // less than double of our power? then attack!
    if (percent <= 100) {
	return true;
    } else {
        return false;
    }
}

function getClanMemberByID(id) {
    var clanm = undefined;
    //alert("clanNextFeed: " + id + ", " + delay);
    for (var i = 0; i < monsters[current_type].clan_size; i++) {
	if (monsters[current_type].clan[i].id == id) {
	    clanm = monsters[current_type].clan[i];
	    break;
	}
    }
    return clanm;
}

(function () {
    // Initialize variables
    auto_timer = GM_getValue('timer',5);
    mstatus = GM_getValue('status',0);
    
    parseURL (location.href);
    // The page has loaded, the ALREADY_GOING variable makes no further sense
    mstatus = (mstatus | ALREADY_GOING) ^ ALREADY_GOING;

    monsters[0] = new Monster(0);
    next_attack = monsters[0].next_attack;
    next_attack_type = 0;
    next_feed = monsters[0].next_feed;
    next_feed_type = 0;

    // Initialize monster stats and next_* variables
    for (var i = 1; i < NR_MONSTERS; i++) {
	monsters[i] = new Monster(i);
	if (monsters[i].next_attack < next_attack) {
	    next_attack = monsters[i].next_attack;
	    next_attack_type = i;
	}
	if (monsters[i].next_feed < next_feed) {
	    next_feed = monsters[i].next_feed;
	    next_feed_type = i;
	}
    }

    switch(current_page) {
	case "feed-result.php":
	// Everything was OK
	    monsters[current_type].last_feed.shift();
	    monsters[current_type].last_feed.push(now);
	    // We used the last feed
	    monsters[current_type].feeds_left--;
	    if (!monsters[current_type].feeds_left) {
		monsters[current_type].next_feed = monsters[current_type].last_feed[0] + 22 * 60 * 60;
	    }
	    var re = /consumer_id=(\d+)/;
	    var id = current_params.match(re)[1];
	    var clanm;
	    if (clanm = getClanMemberByID(id)) {
		clanm.next_feed = now + 22 * 60 * 60;
	    } else {
		clanm = new ClanMember(current_type);
		clanm.id = id;
		clanm.next_feed = now + 22 * 60 * 60;
		monsters[current_type].addOrReplaceClanMember(clanm);
	    }
	    if (mstatus & PREF_AUTOFEED) {
		if (monsters[current_type].next_feed < now) {
		    if (clanm = monsters[current_type].selectClanMember()) {
			monsters[current_type].feed(clanm.id);
		    // Not enough ClanMembers
		    // TODO: Find a way to add more (manually, since history was already checked)
		    } else {
		    // Go to the profile of the next monster
		    // They should know better what to do
			monsters[next_feed_type].showProfile();
		    }
		} else {
		    ((next_feed - now) > auto_timer) ? gcountdown = next_feed - now : gcountdown = auto_timer;
		    monsters[next_feed_type].showProfile();
		} 
	    }
	    break;
	    
	    // Choose who to feed next
	// Main page
	case "side-nav.php":
	    getMonsterStats();
	    // 1st Feed now! Go to the history page and check it
	    if ((mstatus & PREF_AUTOFEED) && (next_feed < now)) {
		if (monsters[current_type].next_feed < now) {
	        gnext_page = APPS_URL + MONSTER_TYPE[current_type + NR_MONSTERS] + "/event-history.php";
	        gmessage = "Adding some " + MONSTER_TYPE[current_type + NR_MONSTERS] + "<br /> to my clan...";
	        gcountdown = auto_timer;
		} else {
		monsters[next_feed_type].showProfile();
		}
	    // 2nd Attack now!
	    } else if ((mstatus & PREF_AUTOATTACK) && (next_attack < now)){
		if (monsters[current_type].next_attack < now) {
		    var defender_type;
		    var random = Math.random();
		    random = Math.floor(3 * random);
		    defender_type = (current_type + random) % NR_MONSTERS;
		    gnext_page = APPS_URL + MONSTER_TYPE[current_type + NR_MONSTERS] + "/fighting-main.php?monster_type=" + MONSTER_TYPE[defender_type];
		    gcountdown = auto_timer;
		    gmessage = "Looking for enemies...";
		} else {
		    monsters[next_attack_type].showProfile();
		    gmessage = "We are going to " + MONSTER_TYPE[next_attack_type + NR_MONSTERS] + " profile...";
		}
	    // 3rd Can't attack or feed now, switch to the profile of the monster that will be
	    // able to do something in the shortest time.
	    } else if (mstatus & (PREF_AUTOATTACK|PREF_AUTOFEED)) {
		var next_action = 'feed';
		var next_action_mtype = 0;
		var next_action_timer = 22 * 60 * 60;
		if (!(mstatus & PREF_AUTOFEED) || (mstatus & PREF_AUTOATTACK) && (next_attack < next_feed)) {
		    next_action = 'attack';
		    next_action_mtype = next_attack_type;
		    next_action_timer = next_attack - now;
		} else {
		    next_action_mtype = next_feed_type;
		    next_action_timer = next_feed - now;
		}
	
		monsters[next_action_mtype].showProfile();	
	        gmessage = "Waiting to " + next_action + "...";
	        gcountdown = next_action_timer;
	    }
	    break;

	case "event-history.php":
	    if ((mstatus & PREF_AUTOFEED) && (current_params == "" || current_params == undefined)) {
		if (mstatus & CLANSELECT_MANUAL) {
		    alert("This should not happen: error 1170. Report this to the script author with the explanation of what you were doing at the time");
		    historyAddCheckboxes();
		} else {
		    monsters[current_type].historyAnalyse();
		    var clanm = monsters[current_type].selectClanMember();
		    if (!clanm) {
			// Go to the profile of the next feedable monster
			((next_feed - now) > auto_timer) ? gcountdown = next_feed - now : gcountdown = auto_timer;
			monsters[current_type].next_feed = now + 2 * 60 * 60;
			monsters[next_feed_type].showProfile();
			gmessage = "Not enough clan members to feed";
		    } else {
			monsters[current_type].feed(clanm.id);
		    }
		}
	    }
	    break;

	// We assume friends are always added manually to the clan
	case "feed-home.php":
	    if ((mstatus & PREF_AUTOFEED) && (current_params == "" || current_params == undefined)) {
		//friendsAddCheckboxes();
		monsters[current_type].showProfile();
		gmessage = "You cannot add people<br /> to your clan manually<br /> for now";
	    }
	    break;
	// Just select a victim friend and hit the submit button
	case "feed-main.php":
	    if ((mstatus & PREF_AUTOFEED) && (!checkErrorMessage("feed"))) {
		divs = getFirstXPathResult("//div[@class='list_item']//input");
		if (divs != undefined && divs != "") {
		    divs.checked = true;
		    gnext_page = findSubmitButton();
		    gmessage = "Choosing victim...";
		    gcountdown = auto_timer;
		// no victim friends remaining! delay the autofeed by 24 hours and go to the profile
		} else {
		    alert("FIXME!");
		    monsters[current_type].next_feed = now + 24 * 60 * 60;
		    monsters[current_type].showProfile();
		}
	    }
	    break;
	case "fighting-main.php":
	    getAttackStats();
	    if (mstatus & PREF_AUTOATTACK) {
		if (monsters[current_type].attacks_left) {
		    selectDefender();
		} else {
		    monsters[current_type].next_attack = now + 4 * 60 * 60;
		    monsters[current_type].showProfile();
		    gmessage = "No more attack for now.<br />Going to profile...";
		}
	    }
	    break;
	case "fighting-confirm.php":
	    getAttackStats();
	    if (mstatus & PREF_AUTOATTACK) {
		var num_attacks = document.getElementsByName("num_attacks");
		if (num_attacks != undefined && num_attacks.length >=1) {
	    	    if (num_attacks[0].options.length > 1) {
			    // change the number of attacks to the last available option
			    num_attacks[0].selectedIndex = num_attacks[0].options.length - 1;
		    }
	   	}
		gnext_page = findSubmitButton();
		gmessage = "Attacking this enemy...";
		gcountdown = auto_timer;
	    }
	    break;
	case "fighting-result.php":
	    try {
		divs = getElementsByClassName("result_rewards", "div")[0].getElementsByTagName("tr");
	    } catch(x){}
	    if (divs !=	undefined && divs.length >= 3) {
		// 0 = heading row, 1 = points row, 2 = bucks row
		//  td 0 = Me , td 1 = Enemy
		// change firstChild to lastChild for enemy results.
		try {
		    var ptsEarned = parseInt(divs[1].firstChild.innerHTML.match(/(\d+(,|\d)*)/i)[1],10);
		    var bksEarned = parseInt(divs[2].firstChild.innerHTML.match(/(\d+(,|\d)*)/i)[1],10);
		} catch(x) {
		    ptsEarned = 0;
		    bksEarned = 0;
		}
		GM_log("Pts: " + ptsEarned + " $: " + bksEarned);//DEBUG
		monsters[current_type].power += ptsEarned;
		monsters[current_type].money += bksEarned; 
		GM_log("Total: Pts: " + ptsEarned + " $: " + bksEarned);//DEBUG
	    } 
	    if (mstatus & PREF_AUTOATTACK) {
		if (monsters[current_type].next_attack < now) {
		    var defender_type;
		    var random = Math.random();
		    random = Math.floor(3 * random);
		    defender_type = (current_type + random) % NR_MONSTERS;
		    gnext_page = APPS_URL + MONSTER_TYPE[current_type + NR_MONSTERS] + "/fighting-main.php?monster_type=" + MONSTER_TYPE[defender_type];
		    gcountdown = auto_timer;
		    gmessage = "Looking for enemies...";
		} else {
		    ((next_attack - now) > auto_timer) ? gcountdown = next_attack - now : gcountdown = auto_timer;
		    monsters[next_attack_type].showProfile();
		    gmessage = "We are going to " + MONSTER_TYPE[next_attack_type + NR_MONSTERS] + " profile...";
		}
	    }
	    break;
	case "bite.php":
	    checkErrorMessage("attack");
	    break;
    }

    insertMenu();
    // Do we have any auto-functions active?
    if (gmessage) {
	startActionTimer();
    } else {
	document.getElementById('monsteraction').innerHTML = "Resting...";
    }

    // Save variables

    for (var i = 0; i < NR_MONSTERS; i++) {
	monsters[i].save();
    }
    GM_setValue('status',mstatus);
//end main function
} ) ()
//end script
} ) ()
/* vim:set tw=0 sts=4 sw=4 ft=javascript: */ 
