var mf; // MarkupFrame
var BlockMarkups = {
	'block':['','','',0],
	'ul':['<ul><li>','</li><li>','</li></ul>',1],
	'dl':['<dl>','</dd>','</dd></dl>',1],
	'ol':['<ol><li>','</li><li>','</li></ol>',1],
	'p':['<p>','','</p>',0],
	'indent':["<div class='indent'>","</div><div class='indent'>",'</div>',1],
	'outdent':["<div class='outdent'>","</div><div class='outdent'>",'</div>',1],
	'pre':['<pre>','','</pre>',0],
	'table':["<table width='100%'>",'','</table>',0] };
var LinkJSPreviewFmt = "<a class='jspreviewlink' href='$tgt'>$txt</a>";

function PQA(x) {
	if (x == undefined) return '';
	var m, out = '', attr = x.match(/[a-zA-Z]+\s*=\s*(?:"[^"]*"|'[^']*'|\S*)/g);
	if (attr) for ( var i = 0; i < attr.length; ++i ) {
		if ( attr[i].search(/^on/i) >= 0 ) continue;
		m = attr[i].match(/^([a-zA-Z]+)\s*=\s*(['"]?)(.*)\2$/);
		out += m[1]+"='"+m[3].replace("'","&#39;")+"' ";
	}
	return out;
}

function MarkupBlock( str, p1 ) {
	var out = '';
	var a, c, i;
	if ( p1 == 'vspace') {
		mf.vs += "\n";
		while ( mf.cs.length ) {
			c = mf.cs.pop();
			if ( c=='pre' || BlockMarkups[c][3] ) { mf.cs.push(c); break; }
			out += BlockMarkups[c][2];
		}
		return out;
	}
	a = (p1 == undefined) ? new Array() : p1.split(',');
	for ( i = a.length; i < 3; ++i ) a[i] = '';
	var code = a[0];
	var depth = parseInt(a[1]);
	var icol = parseInt(a[2]);

	if ( !code ) depth = 1;
	if ( !depth ) depth = String(a[1]).length;
	if (  depth ) depth += mf.idep;
	if ( !icol ) icol = String(a[2]).length;
	if (  icol ) mf.is[depth] = icol + mf.icol;
	mf.idep = mf.icol = 0;

	while ( mf.cs.length > depth ) out += BlockMarkups[ mf.cs.pop() ][2];

	if ( !code ) {
		if ( mf.cs.length && ( mf.cs[mf.cs.length-1] == 'p') ) {
			code = 'p';			out += HTMLPNewline;
		} else if ( depth<2 ) {
			code = 'p';			mf.is[depth] = 0;
		} else {
			code = 'block';		out += HTMLPNewline;
		}
	}

	if ( depth>0 && depth==mf.cs.length && mf.cs[depth-1]!=code ) out += BlockMarkups[ mf.cs.pop() ][2];
	while ( mf.cs.length ) {
		c = mf.cs.pop();
		if ( c==code || BlockMarkups[c][3] ) { mf.cs.push(c); break; }
		out += BlockMarkups[c][2];
	}

	if (mf.vs) {
		out += ( mf.cs[mf.cs.length-1] == 'pre') ? mf.vs : HTMLVSpace;
		mf.vs = '';
	}
	if ( depth==0 ) { return out; }
	if ( depth==mf.cs.length ) { return out + BlockMarkups[code][1]; }
	while ( mf.cs.length < depth-1 ) {
		mf.cs.push('dl');
		mf.is[mf.cs.length] = 0;
		out += BlockMarkups['dl'][0] + '<dd>';
	}
	if ( mf.cs.length < depth ) {
		mf.cs.push(code);
		out += BlockMarkups[code][0];
	}

	return out;
}

function MarkupClose( key ) {
	var out = '';
	if ( ( key === undefined ) || ( mf.closeall[key] !== undefined ) ) {
		var k, ka = [];
		for ( k in mf.closeall ) ka.push(k);
		for ( var i = ka.length-1; i >= 0; --i ) {
			k = ka[i];
			out += mf.closeall[k];
			delete mf.closeall[k];
			if ( k == key ) break;
		}
	}
	return out;
}

function MarkupLink( str, link, suffix ) {
	link = link || str;
	suffix = suffix || '';
	var tgt, txt;
	var m = link.match(/^(.+?)\s*\|\s*#$/);	// [[target |#]] reference links
	if (m) { tgt = m[1]; txt = ++mf.ref; }
	else {
		m = link.match(/^(.+?)\s*\|\s*(.+?)$/);	// [[target | text]]
		if (m) { tgt = m[1]; txt = m[2] + suffix; suffix = ''; }
		else {
			m = link.match(/^(.+?)\s*-+&gt;\s*(.+?)$/);	// [[target | text]]
			if (m) { tgt = m[2]; txt = m[1] + suffix; suffix = ''; }
			else { tgt = link; txt = link.replace(/\([^)]*\)/,'') + suffix; suffix = ''; }
		}
	}
	return LinkJSPreviewFmt.replace('$tgt',tgt).replace('$txt',txt) + suffix;
}

function MarkupCells( str, name, attr ) {
	attr = PQA(attr);
	name = name.toLowerCase();
	var key = name.replace( /end$/, '' );
	if ( key.slice(0,4) == 'cell' ) key = 'cell';
	var out = '<:block>' + MarkupClose(key);
	if ( name.slice(-3) == 'end') return out;
	if ( name == 'table' ) mf.tattr = attr;
	else if ( key.slice(0,4) == 'cell' ) {
		if ( attr.search(/valign=/) < 0 ) attr += " valign='top'";
		if ( !mf.closeall['table'] ) {
			out += "<table "+mf.tattr+"><tr><td "+attr+">";
			mf.closeall['table'] = '</td></tr></table>';
		} else if ( name == 'cellnr')  out += "</td></tr><tr><td "+attr+">";
		else out += "</td><td "+attr+">";
		mf.closeall['cell'] = '';
	} else {
		out += "<div "+attr+">";
		mf.closeall[key] = '</div>';
	}
	return out;
}

function MarkupToHTML() {
	var out = document.getElementById('text').value;
	mf = { 'cs':[], 'vs':'', 'ref':0, 'closeall':{}, 'is':[], 'escape':1, 'idep':0, 'icol':0, 'tattr':'' };
	for ( var i in markup_pat ) out = out.replace( markup_pat[i], markup_rep[i] );
	while ( mf.cs.length ) out += BlockMarkups[ mf.cs.pop() ][2];
	out += MarkupClose();
	document.getElementById('preview').innerHTML = '<pre>'+out.replace( /</g, '&lt;' )+'</pre><hr />'+out;
	//document.getElementById('preview').innerHTML = out;
	return true;
}

function MarkupAddEvent( obj, evt, fn ) {
	if (obj.addEventListener) obj.addEventListener( evt, fn, false );
	else if (obj.attachEvent) obj.attachEvent( 'on'+evt, fn );
}

MarkupAddEvent( window, 'load', function() {
	var et = document.getElementById('text');
	if ( et && document.getElementById('preview') ) {
		MarkupAddEvent( et, 'keyup', MarkupToHTML );
		MarkupAddEvent( et, 'mouseup', MarkupToHTML );
	}
} );