/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*
 * WARNING: this file is supposed to be cross-browser. All browser-specific features
 * should be wrapped with a function call and factored out in the "browser_dependent.js"
 * file. Please, keep it this way.
 *
 */

// -------------------------- global variables ------------------------------

var iframe;
var editor;
var editor_window;
var path;
var formatblock;
var alternatives;
var alternativesTarget;
var class_selector;
var block_selector;
var lastOrigin;
var image_inputs;
var image_controls;

var previousKey;
var modified = false;
var initialized = false;

var imagePrefix = "image";
var imageCounter = 0;
var imageData = new Array();

var sourceMode = false;

// ----------------------- UI-modifying functions ---------------------------

function start(e) {

	if (initialized) {
		alert("already initialized");
		return;
	}
	
	// First of all, setup the editing canvas
	try {
		iframe = document.getElementById('edit');
		editor_window = iframe.contentWindow;
		editor = editor_window.document;
		editor.designMode = "On";
		addEvent(editor,"click",click,true);
		addEvent(editor,"keydown",keypress,true);
		try {
			editor.execCommand("useCSS", false, true);
		} catch(e) {}
	} catch (e) {
		alert("I'm sorry, but Linotype doesn't work on this browser: " + e.name + " " + e.message);
		return;
	}
	
	// If we get here, the browser supports "designMode" so we
	// instrument the active parts of the page
	path = document.getElementById('editpath').firstChild;
	formatblock = document.getElementById('formatblock');
	formatblock.onchange = formatblockChange;
	alternatives = document.getElementById('alternatives');
	block_selector = document.getElementById('block_selector');
	class_selector = document.getElementById('class_selector');
	image_inputs = document.getElementById('image_inputs');
	image_controls = document.getElementById('image_controls');
    document.getElementById("wysiwyg-checkbox").checked = true;

	// Then we instrument the toolbar <div> and turn them into buttons
    divs = document.getElementsByTagName('div');
    for (var i = 0; i < divs.length; i++) {
		var nameclass = getClass(divs[i]);
		if (nameclass == "imagebutton") {
            divs[i].onmousedown = buttonDown;
            divs[i].onmouseup = buttonUp;
            divs[i].onmouseover = buttonOver;
            divs[i].onmouseout = buttonOut;
            divs[i].onclick = buttonClick;
        }
    }

	// Then we instrument the images that might be already contained
	// in the editing canvas.
	instrumentImages(editor);
	
	// set the initialization flag to avoid onload event loops
	initialized = true;
	
	// and here we go!
    window.status = "Welcome to Linotype";
}

function stop(e) {

    /*
     * FIXME (SM): the onload() event isn't cancellable. This means that we can't
     * prevent people from unloading the page and loose their changes. In IE
     * there is a non-standard way to do this which is hacky at hell but does
     * the job. Is there an equivalent thing for moz?
     */

    if (modified) {
        // if ( window.confirm("You havn't saved. You changes will be lost.\nDo you want to continue?") ) {
        //     return;
        // } else {
        //    e.stopPropagation();
        //    e.preventDefault();
        //    e.returnValue = false;
        //    return false;
        // }
    }
}

function updateUI(force) {

	var target = getOrigin();
	
    if (target != lastOrigin || force) {
        lastOrigin = target;
        
        if (!sourceMode) {
            path.nodeValue = getPath(target);
        } else {
            path.nodeValue = "...";
        }
        
		if (target && (target.nodeType == NodeType.TEXT_NODE)) {
            target = target.parentNode;
        }
        
        var format = getBlockFormat(target);
        if (format != -1) {
            formatblock.selectedIndex = format;
            block_selector.style.visibility = "visible";
        } else {
            block_selector.style.visibility = "hidden";
        }
        
        var options = getAlternatives(target);
        if (options) {
            var parent = alternatives.parentNode;
            parent.removeChild(alternatives);
            alternatives = document.createElement('select');
			var type = getClass(target);
            for (i = 0; i < options.length; i++) {
                var option = document.createElement('option');
                option.setAttribute("value", options[i]);
                if (type == options[i]) {
                    option.setAttribute("selected", "true");
                }
                option.appendChild(document.createTextNode(options[i]));
                alternatives.appendChild(option);
            }
            alternatives.onchange = alternativesChange;
            parent.appendChild(alternatives);
            alternativesTarget = target;
            class_selector.style.visibility = "visible";
        } else {
            class_selector.style.visibility = "hidden";
        }
    }
    
    return target;
}

function wysiwyg(enabled) {
    if (enabled) {
        var text = serializeChildren(editor.body);
		var source = editor.createTextNode(text);
        editor.body.innerHTML = "";
        editor.body.appendChild(source);
		setClass(editor.body, "source");
        sourceMode = true;
        updateUI(true);
    } else {
    	var source = getContentSource();
    	editor.body.innerHTML = source;
		setClass(editor.body,"body");
        reinstrumentImages(editor);
        sourceMode = false;
    }
}

function loadContent(content) {
    editor.body.innerHTML = content;
}

function addImage() {
    editor.execCommand("insertimage", false, "template.jpg");
    var img = getOrigin();
    var input = instrumentImg(img, true);
    activateImgInstrumentation(input, img);
}

function instrumentImages(edit) {
    var imgs = detach(editor.getElementsByTagName('img'));
    for (var i = 0; i < imgs.length; i++) {
        instrumentImg(imgs[i], false);
    }
}

function reinstrumentImages(editor) {
	var imgs = detach(editor.getElementsByTagName('img'));
    for (var i = 0; i < imgs.length; i++) {
        reinstrumentImg(imgs[i]);
    }
}

function instrumentImg(img, template) {
    var id = imageCounter++;
    var imgID = imagePrefix + "-" + id;
    var src = img.getAttribute("src");

    img.setAttribute("id", imgID);
    img.setAttribute("ihref", src);
    setTemplate(img, template);

    addEvent(img.parentNode,"DOMNodeRemoved",imageRemoved);
    
    imageData[imgID] = [src, src, template];

    var input = document.createElement("input");
    input.setAttribute("type", "file");
    input.setAttribute("id", imgID + "-input");
    input.setAttribute("size", "1");
    setClass(input, "image_browser");
    addEvent(input,"click", inputChange);
    addEvent(input,"change", inputChange);
    input.style.position = "absolute";
    input.style.visiblility = "hidden";

    image_inputs.appendChild(input);
    
    return input;
}

function reinstrumentImg(img, id) {
    if (!id) {
        var src = img.getAttribute("src");
        var id = src.substring(src.lastIndexOf('/'), src.lastIndexOf('.'));
    }

    var data = imageData[id];
	
	img.setAttribute("id",id);
	img.setAttribute("src",data[0]);
	img.setAttribute("ihref",data[1]);
	setTemplate(img, data[2]);
}

function activateImgInstrumentation(input,img) {
    input.style.left = (iframe.offsetLeft + img.x + 5) + "px";
    input.style.top = (iframe.offsetTop + img.y + 5) + "px";
	input.style.visibility = "visible";
}

function deactivateImgInstrumentation(input) {
    input.style.visibility = "hidden";
    input.name = "";
}

function block() {
	editor.execCommand("formatblock", false, getCommandFormat("P"));
}

function unblock() {
	var block = getParentBlock(getOrigin());
	var parent = block.parentNode;
    var children = block.childNodes;
	for (var i = children.length - 1; i >= 0; i--) {
    	parent.insertBefore(children.item(i),block);
	}
	parent.removeChild(block);
}

// --------------------- Content-related functions -------------------

function getInnerHTML() {
    return editor.body.innerHTML;
}

function getContent() {
	if (sourceMode) wysiwyg(false);
    var content = '<html xmlns="http://www.w3.org/1999/xhtml"><body>';
    content += serializeChildren(editor.body);
    content += '</body></html>';
    return content;
}

// ----------------------- Event functions ---------------------------

function keypress(e) {
	var key, ch = 0
    modified = true;
	if (!e) e = edit.event;
	key = e.keyCode;

	//var target = getPreviousMeaningfulNode(updateUI());

    //window.status = "[" + key + "," + e.shiftKey + "," + e.ctrlKey + "," + e.altKey + "," + e.metaKey + "]";
	
    try {
        // Disable "Back" / "Forward" buttons (Alt|Apple+LeftArrow / Alt|Apple+RightArrow)
        if (e.altKey || e.metaKey) {
            if (key > 0) {
                switch (key) {
                	// FIXME(SM): is seems that these events aren't canceled by
                	// the event cancellation model in Mozilla and Firebird
                	// but if we trigger an alert() box they are stopped
                	// it's hacky, I know, but I can't find a better way and
                	// it is vital that I stop these since it's muscle memory
                	// for MacOS users to use Apple+arrows to move to star/end
                	// of line and if done here we loose all the content without
                	// a warning!!
                    case 37: // left arrow
                    	alert("blocking Alt|Apple+LeftArrow");
                        e.stopPropagation();
                        e.preventDefault();
                        e.returnValue = false;
                        return false;
                    case 39: // right arrow
                    	alert("blocking Alt|Apple+RightArrow");
                        e.stopPropagation();
                        e.preventDefault();
                        e.returnValue = false;
                        return false;
                }
            }
        
        // FIXME(SM): Here is the place to look for advanced keyboard interaction with the
        // schema, for example when doing two returns in a particular location
        // will generate a particular element, but since this is a hell of
        // state control and I'm a lazy ass, we'll do it in the future ;-)
        
        //} else if (key == 13) {
        //	if (previousKey == 13) {
        //   	editor.execCommand("insertparagraph", false, null);
        //	} else if (target.parentNode.nodeName == "H1") {
        //    	//editor.execCommand("insertparagraph", false, null);
        //  }
        
        }
    } catch (e) { }

    previousKey = key;
}

function click() {
    updateUI();
    previousKey = null;
}

function formatblockChange() {
    var selection = formatblock.selectedIndex;
    var format = formatblock.options[selection].value;
	var commandFormat = getCommandFormat(format);
	editor.execCommand("formatblock", false, commandFormat);
    updateUI(true);
    editor_window.focus();
    modified = true;
}

function alternativesChange() {
    var selection = alternatives.selectedIndex;
    var selectionClass = alternatives.options[selection].value;
	setClass(alternativesTarget,selectionClass);
}

function buttonClick() {
    if (this.id == "createlink") {
        var href = prompt("Enter a URL:", "");
        editor.execCommand(this.id, false, href);
    } else if (this.id == "insertimage") {
        addImage();
    } else if (this.id == "block") {
    	block();
    } else if (this.id == "unblock") {
    	unblock();
    } else {
        editor.execCommand(this.id, false, null);
    }
    updateUI(true);
    editor_window.focus();
    modified = true;
}

function buttonDown() {
    this.firstChild.style.left = "1px";
    this.firstChild.style.top = "1px";
    this.style.border="inset 1px";
}

function buttonUp() {
    this.firstChild.style.left = "0px";
    this.firstChild.style.top = "0px";
    this.style.border="outset 1px";
}

function buttonOver() {
    this.style.border="outset 1px";
}

function buttonOut() {
    this.style.border="solid 1px #eee";
}

function imageRemoved(e) {
	var target = getTarget(e,this);
	if (target) {
		var id = target.getAttribute("id");
	    var input = document.getElementById(id + "-input");
	    if (input) deactivateImgInstrumentation(input);
	}
}

function inputChange(e) {
	var input = getTarget(e,this);
    var inputID = input.getAttribute("id");
    var imgID = inputID.substring(0, inputID.indexOf("-input"));
    var img = editor.getElementById(imgID);
    if (input.value != "") {
        var src = "file:///" + input.value;
        var href = imgID + input.value.substring(input.value.lastIndexOf('.'));
        var newImg = document.createElement("img");
        img.parentNode.replaceChild(newImg, img);
        imageData[imgID] = [src, href, false];
        reinstrumentImg(newImg, imgID);
        deactivateImgInstrumentation(input);
        input.setAttribute("name", "save:" + href);
    } else {
        img.parentNode.removeChild(img);
        // this will cause a "node removed" event that will cause
        // the imageRemoved() function to be called, cleaning up
        // the instrumented input field
    }
}

// ------------------------------ end of file --------------------------
