// ==UserScript==
// @name		deviantLIT formatter
// @namespace		http://www.five-by-five.se/v2/code/greasemonkey/
// @description		Allows users to change Poetry/Prose display
// @include		http://www.deviantart.com/deviation/*
// @include		http://deviantart.com/deviation/*
// @exclude		http://www.deviantart.com/deviation/*/favourites/*
// @exclude		http://deviantart.com/deviation/*/favourites/*
// @include		http://www.deviantart.com/view/*
// @include		http://deviantart.com/view/*
// @exclude		http://www.deviantart.com/view/*/favourites/*
// @exclude		http://deviantart.com/view/*/favourites/*
// ==/UserScript==

/*
	Version 0.3.3: 2006-11-15. Kalle Räisänen, xork.deviantart.com
	Based on NekoDramon.deviantart.com's "deviantLIT Friendly Format" v1.1
*/

(function()
{
	var DEFAULT_FONT = 'Verdana, Arial, Helvetica, sans-serif',
	    DEFAULT_FS = 8, DEFAULT_LH = 10, DEFAULT_IND = 0,
	    DEFAULT_BG = 'inherit', DEFAULT_FG = 'black', DEFAULT_WIDTH = 95;
	var SERIF_FONT = 'Georgia, Times New Roman, Times, serif';

	var litstyle;
	var deviation, font, fontsize, lineheight, indent, bgcol, fgcol, width,
       rmblank = 0, formatstring = '', align;

	var litmode = 0;
	var modenames = ['poetry', 'prose', 'scraps'];


	function ucfirst(str) {
		return str.substr(0, 1).toUpperCase() + str.substr(1, str.length);
	}

	function spanify(what)
	{
		var prev = '';
		var children = what.childNodes;

		for(var i = 0; i < children.length; i++) {
			if(children[i].nodeName == 'BR') {
				if(prev == 'SPAN' && i >= 3) {
					var div = document.createElement('div');
					div.className = 'devlit-parabr';
					if(children[i-3].nodeType != 3)
						what.replaceChild(div, children[i-3]);
				}
				var span = document.createElement('span');
				span.className = 'devlit-span';
				what.insertBefore(span, children[i+1]);
			}
			if(children[i].nodeType == 1)
				prev = children[i].nodeName;
			else if(children[i].nodeType == 3 && children[i].nodeValue.match(/[^\s]/)) {
				prev = '';
			}

			if(children[i].hasChildNodes())
				spanify(children[i]);
		}
	}

	function litformat_init()
	{

		var devcontainer = document.getElementById('lit-view');

		if(!devcontainer)
			return;

		var caturi = document.getElementById('catbutton').getAttribute('menuri');

		if(caturi.match(/art\/literature\/prose/))
			litmode = 1;
		else if(caturi.match(/art\/literature\/poetry/))
			litmode = 0;
		else
			litmode = 2;

		var divs = devcontainer.getElementsByTagName('div');

		for(var i = 0; i < divs.length; i++) {
			if(divs[i].className == 'text') {
				deviation = divs[i];
				break;
			}
		}

		deviation.style.margin  = '1em 0 2em';
		deviation.style.padding = '0 .5em 3em';

		var span = document.createElement('span');
		span.className = 'devlit-span';
		deviation.insertBefore(span, deviation.firstChild);
		spanify(deviation);

		var style  = document.createElement('style');
		style.id   = 'litstyle';
		style.type = 'text/css';
		style.innerHTML = 'span.devlit-span   { padding-right: 0; } '
		                 +'div.devlit-pararbr { display: none; }';
		document.getElementsByTagName('head')[0].appendChild(style);
		litstyle = document.getElementById('litstyle');


		var menu = document.createElement('div');

		menu.appendChildren = function() {
			for(var i = 0; i < arguments.length; i++) {
				var obj = (typeof arguments[i] == 'string')
							? document.createTextNode(arguments[i])
							: arguments[i];
				this.appendChild(obj);
			}
		}
		menu.id = 'dlfmenu';
		menu.style.backgroundColor = '#EAF2EE';
		menu.style.fontFamily      = DEFAULT_FONT;
		menu.style.fontSize        = DEFAULT_FS + 'pt';
		menu.style.lineHeight      = 'normal';
		menu.style.margin          = '-20px 2em 1em 1em';
		menu.style.padding         = '.2em 1em .5em';
		menu.style.MozBorderRadius = '0 0 10px 10px';
		menu.style.textAlign       = 'right';
		menu.style.display         = 'block';

		/* menu hash:   tag      innerHTML          callback    */
		var menutags = {
			'Mode':    ['strong','...',              null],
			'Save':    ['a',     'Save',             format_save],
			'Load':    ['a',     'Load',             format_load],
			'Default': ['a',     'Default',          format_default],
			'Copy0':   ['a',     'Copy to Poetry',   format_copy],
			'Copy1':   ['a',     'Copy to Prose',    format_copy],
			'Copy2':   ['a',     'Copy to Scraps',   format_copy],
			'br1':     ['br',    '',                 null],
			'Serif':   ['a',     '...',              seriftoggle],
			'Finc':    ['a',     '++',               fontsizeinc],
			'Fdec':    ['a',     '--',               fontsizedec],
			'Height':  ['a',     'Spacing',          lineheighttoggle],
			'Indent':  ['a',     'Indent',           indenttoggle],
			'Minc':    ['a',     '&raquo; &laquo;',  widthdec],
			'Mdec':    ['a',     '&laquo; &raquo;',  widthinc],
         'br2':     ['br',    '',                 null],
			'Bgcol':   ['a',     'Background',       colourset],
			'Fgcol':   ['a',     'Text colour',      fgcolourset],
			'Rmbl':    ['a',     '... blank lines',  rmblanktoggle],
			'Fmt':     ['a',     '$',                getformatstring]
		};

		menutags['Copy' + litmode][1] = '';

		/* build menu, add callbacks */
		for(var key in menutags) {
			var el = document.createElement(menutags[key][0]);
			el.id        = 'Litf' + key;
			el.innerHTML = menutags[key][1];

			if(menutags[key][0] == 'a') {
				el.href = '#friendlyformat';

				if(menutags[key][2] != null)
					el.addEventListener('click', menutags[key][2], false);

				if(menutags[key][1] == '')
					menu.appendChild(el);
				else
					menu.appendChildren(' [', el, ']');
			} else {
				menu.appendChildren(menutags[key][0] == 'br' ? '' : ' ', el);
			}
		}

		devcontainer.addEventListener(
			'click',
			function(e) {
				if(e.detail == 3) {
					var m = document.getElementById('dlfmenu');
					m.style.display = m.style.display == 'block' ? 'none' : 'block';
					GM_setValue('deviantlit_menudisplay', m.style.display);
				}
			},
			false
		);

		devcontainer.insertBefore(menu, devcontainer.firstChild);

		/*	we have to wait for the deviation-tools menu to figure out
			that it needs to disappear before we can hide our menu.  */
		window.setTimeout(
			'document.getElementById("dlfmenu").style.display = '
				+ '"' + GM_getValue('deviantlit_menudisplay', 'block') + '";',
			550
		);

		format_load();
	}


	function format_update()
	{
		document.getElementById('LitfMode').innerHTML = ucfirst(modenames[litmode]);

		document.getElementById('LitfCopy0').style.fontStyle
			= document.getElementById('LitfCopy1').style.fontStyle
			= document.getElementById('LitfCopy2').style.fontStyle
			= 'normal';

		document.getElementById('LitfSerif').innerHTML =
			(font == DEFAULT_FONT) ? 'Serif' : 'Sans serif';
		document.getElementById('LitfRmbl').innerHTML =
			(rmblank ? 'Show blank lines' : 'Hide blank lines');

		deviation.style.color      = fgcol;
		deviation.style.fontFamily = font;
		deviation.style.fontSize   = fontsize + 'pt';
		deviation.style.lineHeight = (lineheight == 0) ? 'normal' : ((lineheight + 10) / 10);
		deviation.style.marginLeft = (width == 100 ? 0 : (100 - width) / 2) + '%';
		deviation.style.width      = width + '%';

		document.getElementById('lit-view').setAttribute(
			'style',
			'background-color: ' + bgcol + '; '
			+ '-moz-border-radius: 10px; '
			+ 'margin: 10px 3.5% -30px 4.5%; '
			+ 'padding: 1.5em 0 0;'
		);
		litstyle.innerHTML =
			'span.devlit-span  { padding-right: ' + indent + 'em; } ' +
		   'div.devlit-parabr { display: ' + (rmblank ? 'none' : 'block') + ';}';
	}

	function format_default()
	{
		font       = DEFAULT_FONT;
		fontsize   = DEFAULT_FS;
		lineheight = DEFAULT_LH;
		indent     = DEFAULT_IND;
		bgcol      = DEFAULT_BG;
		width      = DEFAULT_WIDTH;
		rmblank    = 0;

		format_update();
	}

	function format_load()
	{
		var mode = modenames[litmode];

		font       = GM_getValue('deviantlit_font_' + mode,       DEFAULT_FONT);
		fontsize   = GM_getValue('deviantlit_fontsize_' + mode,   DEFAULT_FS);
		lineheight = GM_getValue('deviantlit_lh_' + mode,         DEFAULT_LH);
		indent     = GM_getValue('deviantlit_indent_' + mode,     DEFAULT_IND);
		bgcol      = GM_getValue('deviantlit_bgcol_' + mode,      DEFAULT_BG);
		fgcol      = GM_getValue('deviantlit_fgcol_' + mode,      DEFAULT_FG);
		width      = GM_getValue('deviantlit_w_' + mode,          DEFAULT_WIDTH);
		rmblank    = GM_getValue('deviantlit_rmblank_' + mode,    0);

		format_update();
	}

	function format_save()
	{
		var mode = modenames[litmode];

		GM_setValue('deviantlit_font_' + mode,       font);
		GM_setValue('deviantlit_fontsize_' + mode,   fontsize);
		GM_setValue('deviantlit_lh_' + mode,         lineheight);
		GM_setValue('deviantlit_indent_' + mode,     indent);
		GM_setValue('deviantlit_bgcol_' + mode,      bgcol);
		GM_setValue('deviantlit_fgcol_' + mode,      fgcol);
		GM_setValue('deviantlit_w_' + mode,          width);
      GM_setValue('deviantlit_rmblank_' + mode,    rmblank);
	}

	function format_copy()
	{
		var lmode = Number(String(this.id).replace(/[^\d]/g, ''));

		var old = litmode;
		litmode = lmode;
		format_save();
		litmode = old;

		this.style.fontStyle = 'italic';
	}

	function seriftoggle()
	{
		font = (font == DEFAULT_FONT) ? SERIF_FONT : DEFAULT_FONT;
		format_update();
	}

	function fontsizeinc()
	{
		if(fontsize == 20) return false;
		fontsize++;

		format_update();
	}

	function fontsizedec()
	{
		if(fontsize == DEFAULT_FS) return false;
		fontsize--;

		format_update();
	}

	function lineheighttoggle()
	{
		// valid lineheights: 10 => 25 (1.0 => 2.5)
		lineheight = ((lineheight + 5) % 20);

		format_update();
	}

	function indenttoggle()
	{
		indent = (indent + 1) % 5;
		format_update();
	}

	function colourset()
	{
		var bgin = prompt('Enter background colour (leave blank for default):', bgcol);

		if(bgin == null || bgin == bgcol) // user clicked "cancel"
			return;

		bgcol = bgin;

		format_update();
	}

	function fgcolourset()
	{
		var fgin = prompt('Enter text colour (leave blank for default):', fgcol);

		if(fgin == null || fgin == fgcol) return;

		fgcol = fgin;

		format_update();
	}

	function widthinc()
	{
		if(width >= DEFAULT_WIDTH) return;

		width += 2;

		format_update();
	}

	function widthdec()
	{
		if(width <= 30) return false;

		width -= 2;

		format_update();
	}

	function rmblanktoggle()
	{
		rmblank ^= 1;

		format_update();
	}

	function getformatstring()
	{
		var vars = {
			'serif':      'bool',
			'fontsize':   'int',
			'lineheight': 'int',
			'indent':     'int',
			'bgcol':      'string',
			'fgcol':      'string',
			'width':      'int',
			'hideblank':  'bool'
		};

		var curr_fmt = '';
		for(var key in vars) {
			var val = '';
			switch(key) {
				case 'serif':
					val = (font == DEFAULT_FONT) ? 'false' : 'true';
					break;
				case 'hideblank':
					val = rmblank ? 'true' : 'false';
					break;
				case 'lineheight':
					val = (lineheight + 10);
					break;
				default:
					val = eval(key);
					break;
			}
			if(vars[key] == 'string')
				val = '"' + val + '"';
			curr_fmt += key + '=' + val + '; ';
		}

		var fin = prompt('Enter format string:', curr_fmt);

		if(fin == null || fin == '' || fin == curr_fmt) return;

		var formatstring = fin;

		for(var key in vars) {
			var re;
			if(vars[key] == 'string') {
				re = new RegExp(key + ' *= *(".*"|\'.*\') *;');
			} else if(vars[key] == 'int') {
				re = new RegExp(key + ' *= *([0-9]+) *;');
			} else if(vars[key] == 'bool') {
				re = new RegExp(key + ' *= *(true|false) *;');
			} else {
				alert('Danger! Danger! The Universe has imploded!');
			}

			var m = formatstring.match(re);

			if(m != null) {
				var val = m[1];

				switch(key) {
					case 'serif':
						font = (val == 'true') ? SERIF_FONT : DEFAULT_FONT;
						break;
					case 'hideblank':
						rmblank = (val == 'true') ? 1 : 0;
						break;
					case 'lineheight':
						lineheight = val - 10;
						break;
					default:
						eval(key + '=' + val);
						break;
				}
			}
		}

		format_update();
	}


	litformat_init();
})();

