function log () {
	var c = window.console;
	if (c) c.log.apply(c, arguments);
}


function Presentation (target) {
	this.initialize.apply(this, arguments);
}
Presentation.prototype = {
	initialize : function (target, opts) {
		this.target = target;
		this.opts = opts;
		log(MochiKit.Style.getViewportDimensions());

		this.pages = []; // scroll targets: h3 elements
		this.pages_body = []; // page content: h3 siblings
		var self = this;
		var i = 0;
		forEach(this.target.getElementsByTagName('h3'), function (e) {
			self.pages[i] = e;
			self.fold(i);
			i++;
		});

		bindMethods(this);
		addKeybind('j', this.next);
		addKeybind('k', this.prev);
		addKeybind('f', function () {
			self.fold(self.page);
			self.scrollTo(self.pages[self.page]);
		});

		target.appendChild(DIV({'style':'height:'+getViewportDimensions().h+'px'}));
		document.body.appendChild(
			this.info = DIV({'class':'info'}, opts.Title)
		);

		this.page = -1;
		window.scrollTo(0, 0);
		document.title = opts.Title;
		log('initialized');


		if (location.hash.match(/^#p(\d+)/)) {
			var page = Number(RegExp.$1) - 1;

			var self = this;
			var timer = setInterval(function () {
				if (self.pages_body[page].length == 0) {
					clearInterval(timer);
					return;
				}
				self.next();
			}, 1);
		}
	},

	next : function () {
		if (this.page >= 0 && this.pages_body[this.page].length > 0) {
			var e = this.pages_body[this.page].shift();
			log(e);
			e.style.display = 'block';
			var epos = getElementPosition(e);
			var edim = getElementDimensions(e);
			var vpos = getViewportPosition();
			var vdim = getViewportDimensions();
			if (epos.y + edim.h > vpos.y + vdim.h - 40) {
				var p = MochiKit.Position;
				p.prepare();
				window.scrollTo(p.windowOffset.x, epos.y - vdim.h + edim.h + 40);
			}
		} else {
			var t = this.page;
			this.page++;
			if (this.page >= this.pages.length)
				this.page = this.pages.length - 1;
			if (t != this.page) this.scrollTo(this.pages[this.page]);
			this.setTitle();
		}
	},

	prev : function () {
		var t = this.page;
		this.page--;
		if (this.page < 0)
			this.page = 0;
		if (t != this.page) this.scrollTo(this.pages[this.page]);

		this.setTitle();
	},

	fold : function (n) {
		var self = this;
		var e = this.pages[n];
		var nodes = [];
		while (e.nextSibling) {
			e = e.nextSibling;
			if (e.nodeType == 1) {
				if (e.nodeName.toLowerCase() == 'h3') break;
				if (!e.firstChild) continue;
				nodes.push(e);
				e.style.display = 'none';
			}
		}
//		var childs = e.parentNode.childNodes;
//		for (var i = 0, skip = true; i < childs.length; i++) {
//			if (childs[i] == e) {
//				skip = false;
//				continue;
//			}
//			if (skip) continue;
//			e = childs[i];
//			if (e.nodeType == 1) {
//				if (e.nodeName.toLowerCase() == 'h3') break;
//				if (!e.firstChild) continue;
//				nodes.push(e);
//				e.style.display = 'none';
//			}
//		}
		self.pages_body[n] = nodes;
	},

	setTitle : function () {
		var section_title = this.EtoS(this.pages[this.page]);
		document.title = [this.opts.Title, ' - ', section_title].join('');
		while (this.info.firstChild) this.info.removeChild(this.info.firstChild);
		this.info.appendChild(document.createTextNode(section_title));
	},

	scrollTo : function (e) {
		MochiKit.Visual.ScrollTo(e, {
			duration: 0.5
		});
	},

	EtoS : function (e) {
		var self = this;
		var ret = [];
		forEach(e.childNodes, function (i) {
			switch (i.nodeType) {
				case 1: {
					ret.push(self.EtoS(i));
					break;
				}
				case 3: {
					ret.push(i.nodeValue);
					break;
				}
			}
		});
		return ret.join("");
	}

};

function run (data) {
	data = data.split(/\n\n/);
	var meta = {};
	forEach(
		data.shift().split(/\n/),
		function (l) {
			var m = l.match(/^([^:]+?)\s*:\s*([^\n]*)/);
			meta[m[1]] = m[2];
		}
	);
	var body = data.join('\n\n');
	var html = parse(body);
	html = html.replace(/>([^<]+)/g, function () {
		var ret = arguments[1];
		ret = ret.replace(/\[?(https?:\/\/[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+)\]?/g, '<a href="$1">$1</a>');
		ret = ret.replace(/\[?(d:id:([A-Za-z][a-zA-Z0-9_\-]{2,14}))(\:(\d{8}))?(?:(\#|:)([a-zA-Z0-9_]+))?\]?/ig, function () {
			if (arguments[5]) {
				var delim = arguments[5] == ':' ? '/' : '#';
				return [
					'<a href="http://d.hatena.ne.jp/',
					arguments[2],
					'/',
					arguments[4],
					delim,
					arguments[6],
					'">',
					arguments[1],
					arguments[3],
					arguments[5],
					arguments[6],
					'</a>'
				].join('');
			} else {
				return [
					'<a href="http://d.hatena.ne.jp/',
					arguments[2],
					'/',
					arguments[4],
					'">',
					arguments[1],
					arguments[3],
					'</a>'
				].join('');
			}
		});
		return '>'+ret;
	});


	var body = document.body;
	while (body.firstChild) body.removeChild(body.firstChild);

	body.appendChild(H1(null, meta.Title));
	body.appendChild(P({'class':'author'}, meta.Author));
	body.appendChild(P({'class':'description'}, meta.Description));
	body.appendChild(P({'class':'operation'}, 'j: foward, k:back, f:refold'));

	var area = DIV({'class':'area'});
	area.innerHTML = html;

	body.appendChild(area);

	new Presentation(area, meta);
}

function parse (data) {
	var hatena =  new Hatena({
		sectionanchor : "■"
	});
	hatena.parse(data);
	return hatena.html();
}

addLoadEvent(function () {
	log(location.search);

	var filename = location.search.replace(/^\?/, '');

	doSimpleXMLHttpRequest(filename+'?'+(new Date).valueOf()).addCallbacks(
	function (req) {
		try {
			var data = req.responseText;
			run(data);
		} catch (e) {
			log(e);
		}
	},
	function (err) {
		document.body.appendChild(DIV(null, String(err)));
		log(err);
	});
});



