/**

 * plugin.js

 *

 * Released under LGPL License.

 * Copyright (c) 1999-2015 Ephox Corp. All rights reserved

 *

 * License: http://www.tinymce.com/license

 * Contributing: http://www.tinymce.com/contributing

 */



/*global tinymce:true */



tinymce.PluginManager.add('layer', function(editor) {

	function getParentLayer(node) {

		do {

			if (node.className && node.className.indexOf('mceItemLayer') != -1) {

				return node;

			}

		} while ((node = node.parentNode));

	}



	function visualAid(e) {

		var dom = editor.dom;



		tinymce.each(dom.select('div,p', e), function(e) {

			if (/^(absolute|relative|fixed)$/i.test(e.style.position)) {

				if (e.hasVisual) {

					dom.addClass(e, 'mceItemVisualAid');

				} else {

					dom.removeClass(e, 'mceItemVisualAid');

				}



				dom.addClass(e, 'mceItemLayer');

			}

		});

	}



	function move(d) {

		var i, z = [], le = getParentLayer(editor.selection.getNode()), ci = -1, fi = -1, nl;



		nl = [];

		tinymce.walk(editor.getBody(), function(n) {

			if (n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position)) {

				nl.push(n);

			}

		}, 'childNodes');



		// Find z-indexes

		for (i = 0; i < nl.length; i++) {

			z[i] = nl[i].style.zIndex ? parseInt(nl[i].style.zIndex, 10) : 0;



			if (ci < 0 && nl[i] == le) {

				ci = i;

			}

		}



		if (d < 0) {

			// Move back



			// Try find a lower one

			for (i = 0; i < z.length; i++) {

				if (z[i] < z[ci]) {

					fi = i;

					break;

				}

			}



			if (fi > -1) {

				nl[ci].style.zIndex = z[fi];

				nl[fi].style.zIndex = z[ci];

			} else {

				if (z[ci] > 0) {

					nl[ci].style.zIndex = z[ci] - 1;

				}

			}

		} else {

			// Move forward



			// Try find a higher one

			for (i = 0; i < z.length; i++) {

				if (z[i] > z[ci]) {

					fi = i;

					break;

				}

			}



			if (fi > -1) {

				nl[ci].style.zIndex = z[fi];

				nl[fi].style.zIndex = z[ci];

			} else {

				nl[ci].style.zIndex = z[ci] + 1;

			}

		}



		editor.execCommand('mceRepaint');

	}



	function insertLayer() {

		var dom = editor.dom, p = dom.getPos(dom.getParent(editor.selection.getNode(), '*'));

		var body = editor.getBody();



		editor.dom.add(body, 'div', {

			style: {

				position: 'absolute',

				left: p.x,

				top: (p.y > 20 ? p.y : 20),

				width: 100,

				height: 100

			},

			'class': 'mceItemVisualAid mceItemLayer'

		}, editor.selection.getContent() || editor.getLang('layer.content'));



		// Workaround for IE where it messes up the JS engine if you insert a layer on IE 6,7

		if (tinymce.Env.ie) {

			dom.setHTML(body, body.innerHTML);

		}

	}



	function toggleAbsolute() {

		var le = getParentLayer(editor.selection.getNode());



		if (!le) {

			le = editor.dom.getParent(editor.selection.getNode(), 'DIV,P,IMG');

		}



		if (le) {

			if (le.style.position.toLowerCase() == "absolute") {

				editor.dom.setStyles(le, {

					position: '',

					left: '',

					top: '',

					width: '',

					height: ''

				});



				editor.dom.removeClass(le, 'mceItemVisualAid');

				editor.dom.removeClass(le, 'mceItemLayer');

			} else {

				if (!le.style.left) {

					le.style.left = 20 + 'px';

				}



				if (!le.style.top) {

					le.style.top = 20 + 'px';

				}



				if (!le.style.width) {

					le.style.width = le.width ? (le.width + 'px') : '100px';

				}



				if (!le.style.height) {

					le.style.height = le.height ? (le.height + 'px') : '100px';

				}



				le.style.position = "absolute";



				editor.dom.setAttrib(le, 'data-mce-style', '');

				editor.addVisual(editor.getBody());

			}



			editor.execCommand('mceRepaint');

			editor.nodeChanged();

		}

	}



	// Register commands

	editor.addCommand('mceInsertLayer', insertLayer);



	editor.addCommand('mceMoveForward', function() {

		move(1);

	});



	editor.addCommand('mceMoveBackward', function() {

		move(-1);

	});



	editor.addCommand('mceMakeAbsolute', function() {

		toggleAbsolute();

	});



	// Register buttons

	editor.addButton('moveforward', {title: 'layer.forward_desc', cmd: 'mceMoveForward'});

	editor.addButton('movebackward', {title: 'layer.backward_desc', cmd: 'mceMoveBackward'});

	editor.addButton('absolute', {title: 'layer.absolute_desc', cmd: 'mceMakeAbsolute'});

	editor.addButton('insertlayer', {title: 'layer.insertlayer_desc', cmd: 'mceInsertLayer'});



	editor.on('init', function() {

		if (tinymce.Env.ie) {

			editor.getDoc().execCommand('2D-Position', false, true);

		}

	});



	// Remove serialized styles when selecting a layer since it might be changed by a drag operation

	editor.on('mouseup', function(e) {

		var layer = getParentLayer(e.target);



		if (layer) {

			editor.dom.setAttrib(layer, 'data-mce-style', '');

		}

	});



	// Fixes edit focus issues with layers on Gecko

	// This will enable designMode while inside a layer and disable it when outside

	editor.on('mousedown', function(e) {

		var node = e.target, doc = editor.getDoc(), parent;



		if (tinymce.Env.gecko) {

			if (getParentLayer(node)) {

				if (doc.designMode !== 'on') {

					doc.designMode = 'on';



					// Repaint caret

					node = doc.body;

					parent = node.parentNode;

					parent.removeChild(node);

					parent.appendChild(node);

				}

			} else if (doc.designMode == 'on') {

				doc.designMode = 'off';

			}

		}

	});



	editor.on('NodeChange', visualAid);

});

