<?xml version="1.0" encoding="utf-8"?>
<mx:ApolloApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
	initialize="init()" >

	<mx:Script>
	<![CDATA[
		import flash.html.JavaScriptFunction;
		import mx.events.IndexChangedEvent;
		import flash.html.JavaScriptObject;
		import flash.utils.getTimer;
		import flash.filesystem.*;
		
		private var page:int = 1;
		private var t:int = 0;
		private var tips:int = 0;
		private var tipData:Array = ["[[no tips loaded]]"];
		private var currentPage:int = 0;
		
		// called when app starts up
		public function init():void {
			prog.visible = false;
			hidden.addEventListener(Event.HTML_RENDER, rendered);
			loadData();
		}		
		
		// load application state, and the proceed to load
		// any saved tips
		public function loadData():void {
			var file:File = File.appStorageDirectory;
			file = file.resolve("state.dat");
			trace(file.url);
			var fileStream:FileStream = new FileStream();
			try {
				fileStream.open(file, FileMode.READ);
				tips = fileStream.readInt();
				page = fileStream.readInt();
				currentPage = fileStream.readInt();
				//var str:String = fileStream.readUTF();
				//trace("loaded "+str.length+" bytes");
				fileStream.close();
			} catch (e:Error) {
				trace("could not load data");
			}
			for(var i:Number=0; i<tips; i++) {
				tipData[i] = loadTip(i);
			}
			updateHTML();
			go.label = "Load page "+page;
			stat.text = tips+" tips loaded.";			
		}
		
		// save application state
		public function saveData():void {
			var file:File = File.appStorageDirectory;
			file = file.resolve("state.dat");
			var fileStream:FileStream = new FileStream();
			try {
				fileStream.open(file, FileMode.WRITE);
			} catch (e:Error) {
				trace("could open file for writing");
				return;
			}			
			try {
				fileStream.writeInt(tips);
				fileStream.writeInt(page);
				fileStream.writeInt(currentPage);
				trace("saved data");
			} catch (e:IOError) {
				trace("could not save data");
			}
			fileStream.close();
		}
		
		// save a tip to disk
		// n = tip number
		// text = content of the tip
		public function saveTip(n:int, text:String):Boolean {
			var file:File = File.appStorageDirectory;
			var fname:String = "tip_"+n+".dat";
			file = file.resolve(fname);
			var fileStream:FileStream = new FileStream();
			var ret:Boolean = true;
			try {
				fileStream.open(file, FileMode.WRITE);
			} catch (e:Error) {
				trace("could open "+fname+" for writing");
				return false;
			}			
			try {
				fileStream.writeUTF(text);
			} catch (e:IOError) {
				trace("could not save data to "+fname);
				ret = false;
			}
			fileStream.close();					
			
			return ret;
		}
				
		// load a tip from disk.
		// n = tip number
		// returns null if it fails
		public function loadTip(n:int):String {
			var file:File = File.appStorageDirectory;
			var fname:String = "tip_"+n+".dat";
			file = file.resolve(fname);
			var fileStream:FileStream = new FileStream();
			var str:String;
			try {
				fileStream.open(file, FileMode.READ);
				str = fileStream.readUTF();
				trace("loaded "+str.length+" bytes");
				fileStream.close();
			} catch (e:Error) {
				trace("could not load "+fname);
			}
			return str;
		}						
		
		public function rendered(e:Event):void {
			trace("rendered "+(getTimer()-t)/1000);
		}

		public function getPage():void {
			t = getTimer();
			trace("calling getpage... ");
			
			// listen for when page is finished loading
			hidden.addEventListener(Event.COMPLETE, pageLoaded);
			
			// build URL to access the forum
			var url:String = "http://www.kirupa.com/forum/showthread.php?t=223798";
			if(page > 1)
				url += "&page="+page;
			
			// we use a hidden HTML control, so the user does not
			// see the forums being rendered.
			// TODO: Optimize this, so it doesn't bother to load things
			//       like images, css, etc (since we don't want those anyway)
			hidden.location = url;
			
			stat.text = "Loading page "+page+"...";
			prog.visible=true;
			rend = 0;
		}
		
		private var rend:int ;
		
		public function pageLoaded(e:Event):void {
			prog.visible=false;
			hidden.removeEventListener(Event.COMPLETE, pageLoaded);
			page++;
			go.label = "Load page "+page;
			stat.text = "Ready";
			trace("page loaded "+(getTimer()-t)/1000);

			var win:JavaScriptObject = hidden.htmlControl.window; // 'window' JS object
			var doc:JavaScriptObject = win.document; // 'document' JS object
			
			// pull out all the 'div's from the page
			// (no idea why this is a 'JavaScriptFunction' and not
			// a 'JavaScriptObject', but that's what it is)
			var divs:JavaScriptFunction = doc.getElementsByTagName('div');

			trace(typeof(divs) +" / "+divs.toString());
			trace("found "+divs.length+" divs");
			
			var str:String = "";
			var n:int = 0;
			var last:String;
			
			// loop through all the divs
			for(var i:int=0; i<divs.length; i++) {
				var id:String = divs[i].id;
				var cls:String = divs[i].className;
				
				// a div of class 'smallfont' always precedes each tip
				// and it contains the title.
				// so store it.
				if(cls == "smallfont")
					last = divs[i].innerHTML;
				
				if(id.indexOf("post_message_") == 0)
				{
					// these filter out some unwanted posts
					// (posts from noobs commenting on the tips :P )
					if(last.length < 30) continue; 
					if(last.indexOf("strong") < 0) continue;
					if(last.indexOf("ActionScript 3 Tip of the Day") > 0) continue;
					
					// create html string for the tip
					str  = "<hr><b>Tip "+(tips+1)+": "+last+"</b><br/><hr>";
					str += divs[i].innerHTML+"<br/><br/>";
					
					// store the data for that tip in our array
					tipData[tips] = str;
					
					// save the tip to disk
					saveTip(tips, str);
					
					tips++;
					n++;
				}					
			}
			
			updateHTML();
			trace(n+" posts found");
			stat.text = tips+" tips loaded.";
			saveData(); // store application state
		}
		
		// show the next tip
		public function nextPage():void {
			if(currentPage+1 >= tips) return;
			currentPage++;
			updateHTML();
		}

		//show the previous tip
		public function prevPage():void {
			if(currentPage-1 < 0) return;
			currentPage--;
			updateHTML();
		}
		
		// update contents of the visible HTML control
		public function updateHTML():void {
			html.htmlText = tipData[currentPage];
			if(tips > 0)
				pagelbl.text = (currentPage+1)+" / "+tips;
			else
				pagelbl.text = "";
		}
	]]>
	</mx:Script>

	<mx:VBox horizontalAlign="center" width="100%" height="100%">		
		<mx:HBox verticalAlign="middle">
			<mx:Button id="go" label="Load page 1" click="getPage()" />
			<mx:Label id="stat" text="Ready"  width="152"/>
			<mx:ProgressBar height="14" width="100%" id="prog" indeterminate="true" visible="true" labelPlacement="center"/>
		</mx:HBox>
		<mx:HBox verticalAlign="middle">
			<mx:Button id="prev" label="&lt;&lt; Prev Tip" click="prevPage()" />
			<mx:Label id="pagelbl" text="99 / 99"  width="61" textAlign="center" />
			<mx:Button id="next" label="Next Tip &gt;&gt;" click="nextPage()" />
		</mx:HBox>		
		<mx:HTML id="html" width="100%" height="100%"/>
	</mx:VBox>
	<mx:HTML id="hidden" width="10" height="10" visible="false"/>
	
</mx:ApolloApplication>
