/*
    Base, version 1.0.2
    Copyright 2006, Dean Edwards
    License: http://creativecommons.org/licenses/LGPL/2.1/
*/

var Base = function() {
    if (arguments.length) {
        if (this == window) { // cast an object to this class
            Base.prototype.extend.call(arguments[0], arguments.callee.prototype);
        } else {
            this.extend(arguments[0]);
        }
    }
};

Base.version = "1.0.2";

Base.prototype = {
    extend: function(source, value) {
        var extend = Base.prototype.extend;
        if (arguments.length == 2) {
            var ancestor = this[source];
            // overriding?
            if ((ancestor instanceof Function) && (value instanceof Function) &&
                ancestor.valueOf() != value.valueOf() && /\bbase\b/.test(value)) {
                var method = value;
            //  var _prototype = this.constructor.prototype;
            //  var fromPrototype = !Base._prototyping && _prototype[source] == ancestor;
                value = function() {
                    var previous = this.base;
                //  this.base = fromPrototype ? _prototype[source] : ancestor;
                    this.base = ancestor;
                    var returnValue = method.apply(this, arguments);
                    this.base = previous;
                    return returnValue;
                };
                // point to the underlying method
                value.valueOf = function() {
                    return method;
                };
                value.toString = function() {
                    return String(method);
                };
            }
            return this[source] = value;
        } else if (source) {
            var _prototype = {toSource: null};
            // do the "toString" and other methods manually
            var _protected = ["toString", "valueOf"];
            // if we are prototyping then include the constructor
            if (Base._prototyping) _protected[2] = "constructor";
            for (var i = 0; (name = _protected[i]); i++) {
                if (source[name] != _prototype[name]) {
                    extend.call(this, name, source[name]);
                }
            }
            // copy each of the source object's properties to this object
            for (var name in source) {
                if (!_prototype[name]) {
                    extend.call(this, name, source[name]);
                }
            }
        }
        return this;
    },

    base: function() {
        // call this method from any other method to invoke that method's ancestor
    }
};

Base.extend = function(_instance, _static) {
    var extend = Base.prototype.extend;
    if (!_instance) _instance = {};
    // build the prototype
    Base._prototyping = true;
    var _prototype = new this;
    extend.call(_prototype, _instance);
    var constructor = _prototype.constructor;
    _prototype.constructor = this;
    delete Base._prototyping;
    // create the wrapper for the constructor function
    var klass = function() {
        if (!Base._prototyping) constructor.apply(this, arguments);
        this.constructor = klass;
    };
    klass.prototype = _prototype;
    // build the class interface
    klass.extend = this.extend;
    klass.implement = this.implement;
    klass.toString = function() {
        return String(constructor);
    };
    extend.call(klass, _static);
    // single instance
    var object = constructor ? klass : _prototype;
    // class initialisation
    if (object.init instanceof Function) object.init();
    return object;
};

Base.implement = function(_interface) {
    if (_interface instanceof Function) _interface = _interface.prototype;
    this.prototype.extend(_interface);
};

/*
 * Copyright Kitpages 2006
 * need jQuery 1.2.3
 * need jQuery Form Plugin 2.0.2
 */

////
// Package definition
////
var Kitpages = {
    util: {},
    mvc: {},
    log: {},
    widget: {},
    custom: {}
};

////
// Logger
////
Kitpages.log = {
    debug: function(msg) {
		if ( typeof(debugMode) != "undefined" ) {
			//console.debug("DEBUG:"+msg);
		}	
    },
    info: function(msg) {
        return true;      	
    },
    warning: function(msg) {
        return true;    	
    },
    error: function(msg) {
		if ( typeof(debugMode) != "undefined" ) {
        	//console.error("DEBUG:"+msg);
		}        	
    }
}

////
// utils
////
var Try = {
  these: function() {
    var returnValue;

    for (var i = 0, length = arguments.length; i < length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) { }
    }

    return returnValue;
  }
};

//////
////
// MVC Definition
////
//////

////
// Model
////
Kitpages.mvc.BasicModel = Base.extend ({
    constructor: function(initValues) {
        //Kitpages.log.debug("init BasicModel initValue="+initValues.uiId);
        this.subInit(initValues);
    },

    subInit: function(initValues) {
        this.content = {};
        this.ui = $("#"+initValues.uiId);
        this.fromServiceUrl = initValues.fromServiceUrl;
        this.toServiceUrl = initValues.toServiceUrl;

        if (this.ui == undefined) {
            Kitpages.log.error("the id '"+initValues.uiId+"' given in the model is wrong");
        }
        this.ui.kitpagesModel = this;
    },

    ////
    // standard methods
    ////
    fromService: function(controller) {
        //Kitpages.log.debug("fromService : call "+this.fromServiceUrl);
        if (this.fromServiceUrl != null) {
            var model = this;
            $.ajax({
                type: "GET",
                url: this.fromServiceUrl,
                dataType: "text",
                success: function (data) {
                    model.fromServiceSuccessCallback(data, controller);
                },
                error: function (data) {
                    model.fromServiceFailureCallback(data, controller);
                }
            });
        }
    },

    toService: function(controller) {
        //Kitpages.log.debug("toService testString="+controller.testString);
        if (this.toServiceUrl != null) {
            this.fromUi();
            var model = this;
            var ajaxContent = { __content: JSON.stringify(this.content)};
            $.ajax({
                type: "POST",
                url: model.toServiceUrl,
                dataType: "text",
                data: ajaxContent,
                success: function (data) {
                    model.toServiceSuccessCallback(data, controller);
                },
                error: function (data) {
                    model.toServiceFailureCallback(data, controller);
                }
            });
        }
    },

    fromUi: function() {
        // to be overriden
    },

    toUi: function() {
        // to be overriden
    },

    ////
    // added methods
    ////
    setContent: function(content) {
        this.content = content;
    },

    ////
    // callback methods
    ////
    fromServiceSuccessCallback: function(data, controller) {
        //Kitpages.log.debug("fromServiceSuccessCallback1");
        // get response
        var response;
        try {
            response = JSON.parse(data);
        }
        //Kitpages.log.debug("fromService : response "+this.model.fromServiceUrl+" txt="+originalRequest.responseText);
        catch (e) {
            Kitpages.log.error("wrong JSON response : "+data);
            controller.onFromServiceFailure(data);
            return false;
        }
        // check code response
        if (response.code != "OK") {
            Kitpages.log.error("code != OK in response : "+data);
            controller.onFromServiceSuccess(data);
            return false;
        }
        // parse response content
        if (response.content) {
            var json = response.content;
            if (json != false) {
                this.content = json;
            }
            else {
                this.content = {};
            }
        }
        else {
            this.content = {};
        }
        // update UI
        if (this.onFromServiceBeforeToUi(response)) {
            this.toUi();
        }
        this.onFromServiceAfterToUi(response);
        // fire success event
        controller.onFromServiceSuccess(data);
    },
    
    onFromServiceBeforeToUi: function(response) {
        return true;
    },
    
    onFromServiceAfterToUi: function(response) {
    },

    fromServiceFailureCallback: function(data,controller) {
        Kitpages.log.error("server does'nt respond on URL "+this.fromServiceUrl);
        controller.onFromServiceFailure(data);
    },

    toServiceSuccessCallback: function(data,controller) {
        //Kitpages.log.debug("JSON response 0: "+originalRequest.responseText);
        var response;
        try {
            response = JSON.parse(data);
        }
        //Kitpages.log.debug("JSON response 1: "+originalRequest.responseText);
        catch (e) {
            Kitpages.log.error("manageResponse, wrong JSON response : "+data);
            controller.onToServiceFailure(data);
            return;
        }
        //Kitpages.log.debug("before onToServiceSuccess");
        //Kitpages.log.debug("toServiceSuccessCallback testString="+this.testString);
        controller.onToServiceSuccess(data);
    },

    toServiceFailureCallback: function(data, controller) {
        Kitpages.log.error("server doesn't respond on URL"+this.toServiceUrl);
        controller.onToServiceFailure(data);
    }

});

/**
 * Class used for managing model of a form
 * Example :
var formModel = new Kitpages.mvc.FormModel({
    uiId:"myForm",
    fromServiceUrl:"http://toto.com/service/fillMyInfoForm",
    toServiceUrl:"http://toto.com/service/saveMyInfoForm"
});
formModel.fromService(); // initialize the model and send to UI

formModel.toService(); // get data from UI and send to service (for saving)
 */
Kitpages.mvc._fieldValue = function(el, successful) {
    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
    if (typeof successful == 'undefined') successful = true;

    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
        (t == 'checkbox' || t == 'radio') && !el.checked ||
        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
        tag == 'select' && el.selectedIndex == -1))
            return null;

    if (tag == 'select') {
        var index = el.selectedIndex;
        if (index < 0) return null;
        var a = [], ops = el.options;
        var one = (t == 'select-one');
        var max = (one ? index+1 : ops.length);
        for(var i=(one ? index : 0); i < max; i++) {
            var op = ops[i];
            if (op.selected) {
                // extra pain for IE...
                var v = $.browser.msie && !(op.attributes['value'].specified) ? op.text : op.value;
                if (one) return v;
                a.push(v);
            }
        }
        return a;
    }
    return el.value;
};
 
Kitpages.mvc.FormModel = Kitpages.mvc.BasicModel.extend ({
    constructor: function(initValues) {
        //Kitpages.log.debug("init FormModel initValue="+initValues.uiId);
        this.base(initValues);
    },

    ////
    // communication model<->ui
    ////
    fromUi: function() {
        var semantic = true;
        var form = $(this.ui)[0];
        var a = [];

        var els = semantic ? form.getElementsByTagName('*') : form.elements;
        if (!els) return a;
        for(var i=0, max=els.length; i < max; i++) {
            var el = els[i];
            var n = el.name;
            if (!n) continue;
        
            var v = Kitpages.mvc._fieldValue(el, true);
    
            if (v && v.constructor == Array) {
                for(var j=0, jmax=v.length; j < jmax; j++)
                    a.push({name: n, value: v[j]});
            }
    
            else if (v !== null && typeof v != 'undefined')
                a.push({name: n, value: v});
        }
        
        // transform array format
        var b = {};
        for (var i=0, max=a.length ; i < max ; i++) {
            var el = a[i];
            var name = el.name;
            var value = el.value;
            if (undefined != b[name]) {
                if (b[name].constructor != Array) {
                    b[name] = [b[name]];
                }
                b[name][b[name].length] = value;
                //alert("name="+name+";b.length="+b[name].length);
            }
            else {
                b[name] = value;
            }
        }
        this.content = b;
    },

    toUi: function() {
        var semantic = true;
        var form = $(this.ui)[0];
        //alert("ui="+form.id);
        var a = this.content;

        var els = semantic ? form.getElementsByTagName('*') : form.elements;
        if (!els) return false;
        for(var i=0, max=els.length; i < max; i++) {
            var tag = els[i];
            var n = tag.name;
            if (!n) continue;
            
            var tagName = tag.tagName.toLowerCase();
            //Kitpages.log.debug("elementId="+tag.id+" ; name="+tag.name+" ; type="+tag.type+" ; tagName="+tag.tagName.toLowerCase());
            switch (tagName) {
            case "select":
                if (undefined != this.content[tag.name]) {
                    var tmpContent = this.content[tag.name];
                    var valueArray = [];
                    if (tmpContent && tmpContent.constructor == Array) {
                        valueArray = tmpContent;
                    }
                    else {
                        valueArray = [tmpContent];
                    }
                    $(tag).val(valueArray);
                    /*
                    var optionList = tag.getElementsByTagName('*');
                    for (k=0 ; k<optionList.length ; k++) {
                        optionTag = optionList[k];
                        var optionTagName = optionTag.tagName.toLowerCase();
                        if (optionTagName == "option") {
	                        if (valueArray.indexOf(optionTag.value) != -1) {
	                            optionTag.selected = true;
	                        }
	                        else {
	                            optionTag.selected = false;
	                        }
	                    }
                    }
                    */
                }
                break;
            case "input":
                if (undefined != this.content[tag.name]) {
                    if ( (tag.type == "text") ||
                         (tag.type == "hidden") || 
                         (tag.type == "password") ) {
                        tag.value = this.content[tag.name];
                    }
                    if (tag.type == "checkbox") {
                        var tmpContent = this.content[tag.name];
                        if (tmpContent && tmpContent.constructor == Array) {
                            var valueArray = tmpContent;
                        }
                        else {
                            var valueArray = [tmpContent];
                        }
                        $(tag).val(valueArray);
                        /*
                        if (valueArray.indexOf(tag.value) != -1) {
                            tag.checked = true;
                        }
                        else {
                            tag.checked = false;
                        }
                        */
                    }
                    if (tag.type == "radio") {
                        if (tag.value == this.content[tag.name]) {
                            tag.checked = true;
                        }
                    }
                }
                break;
            case "textarea":
                //Kitpages.log.debug("before0 tinyMCE");
                if (undefined != this.content[tag.name]) {
                    //Kitpages.log.debug("before1 tinyMCE content="+this.content[tag.name]);
                    //new Insertion.Top(tag,this.content[tag.name]);
                    $(tag).text(this.content[tag.name]);
                    //Kitpages.log.debug("before2 tinyMCE");
/*                    if (tinyMCE) {
                        //Kitpages.log.debug("in tinyMCE");
                        tag.value = this.content[tag.name];
                        tinyMCE.updateContent(tag.id);
                    }
*/
                    //Kitpages.log.debug("after tinyMCE");
                    //tag.appendChild(document.createTextNode(this.content[tag.name]));
                }
                break;
            }
        }
    }
});

Kitpages.mvc.UploadModel = Kitpages.mvc.BasicModel.extend ({
    constructor: function(initValues) {
        //Kitpages.log.debug("init UploadModel initValue="+initValues.uiId);
        this.base(initValues);
        var uploadForm = (this.ui)[0];
        $(uploadForm).prepend('<iframe id="'+this.ui.attr("id")+'_uploadTarget" name="'+this.ui.attr("id")+'_uploadTarget" src="" style="width:0px;height:0px;border:0"></iframe>');
        $(uploadForm).append('<div id="'+this.ui.attr("id")+'_uploadProgressBar" style="display: none">Transfert en cours...</div>');
        var targetString = this.ui.attr("id")+"_uploadTarget";
        uploadForm.target = targetString;
        uploadForm.action = initValues.toServiceUrl;
    },

    ////
    // standard methods
    ////
    toService: function(controller) {
        var uploadForm = (this.ui)[0];
        var model = this;
        $("#"+this.ui.attr("id")+"_uploadProgressBar").show();
        var uploadTarget = $("#"+this.ui.attr("id")+"_uploadTarget");
        $(uploadTarget).load(function() {
            console.debug("onload iframe");
	        $("#"+model.ui.attr("id")+"_uploadProgressBar").hide();
	        //var data = $(uploadTarget).text();
	        
	        var data = Try.these (
	            function() {
	                var ret = uploadTarget[0].contentDocument.body.textContent;
	                return ret;
	            },
	            function() {
	                var ret = uploadTarget[0].contentWindow.document.body.innerText;
	                return ret;
	            },
	            function() {
	                var ret = uploadTarget[0].document.body.textContent;
	                return ret;
	            }
	        );
	        console.debug("data="+data);
	                
            model.toServiceSuccessCallback(data,controller);
        });
        console.debug("before submit");
        uploadForm.submit();
        console.debug("after submit");
    },
    
    ////
    // communication model<->ui
    ////
    fromUi: function() {},

    toUi: function() {}
});

////
// Controllers
////
Kitpages.mvc.Controller = Base.extend ({
    constructor: function(model, elementId, eventNameWithoutOn, onResultAction) {
        //Kitpages.log.debug("init Controller initValue="+elementId+" event="+eventNameWithoutOn);
        this.subInit(model, elementId, eventNameWithoutOn, onResultAction);
    },
    subInit: function(model, elementId, eventNameWithoutOn, onResultAction) {
        this.isToServiceRunning = false
        this.model = model;
        this.onResultAction = onResultAction;
        this.eventElementId = elementId;
        var controller = this;
        model.fromService(controller);
        // submit
        //Kitpages.log.debug("controller observe:"+elementId+" "+eventNameWithoutOn+" className="+this.className);
        //Event.observe(elementId, eventNameWithoutOn, this._onControllerEvent.valueOfThis(this), false);
        $("#"+elementId).bind(
            eventNameWithoutOn,
            function() {
                controller._onControllerEvent();
            }
        );
    },

    onToServiceFailure: function(responseText) {
        //Kitpages.log.debug("onToServiceFailure, responseText="+responseText);
        $("#errorMessage").prepend('<li>Problème technique</li>');
        this.onToServiceShutdownCallback();
    },

    onFromServiceFailure: function(responseText) {
        $("#errorMessage").prepend('<li>Problème technique</li>');
    },

    onFromServiceSuccess: function(responseText) {
        //Kitpages.log.debug("onFromServiceSuccess");
        var response;
        try {
            response = JSON.parse(responseText);
        }
        catch (e) {
            $("#errorMessage").prepend('<li>Technical error, FromServiceSuccess wrong json:</li>');
            return;
        }
        var errorList = response.messageList;
        for (var i=0; i < errorList.length ; i++) {
            var error = errorList[i];
            $("#errorMessage").prepend('<li>'+error+'</li>');
        };
    },

    onToServiceSuccess: function(responseText) {
        //Kitpages.log.debug("onToServiceSuccess, responseText="+responseText);
        var response;
        try {
            response = JSON.parse(responseText);
        }
        catch (e) {
            $("#errorMessage").prepend('<li>Technical error, ToServiceSuccess wrong json:</li>');
            return;
        }
        var action = this.onResultAction[response.code];
        if (undefined == action) {
            action = this.onResultAction["DEFAULT"];
            if (undefined == action) {
                $("#errorMessage").prepend('<li>Erreur technique</li>');
                Kitpages.log.error("no action defined, and no DEFAULT action, responde.code="+response.code+";formId="+this.formDescription.id);
                return false;
            }
        }
        if (undefined != action.redirect) {
            //Kitpages.log.debug("redirection to:"+action.redirect);
            location.href = action.redirect;
        }
        if (undefined != action.errorCallback) {
            $("#"+action.errorCallback).empty();
            var errorList = response.messageList;
            for (var i=0; i < errorList.length ; i++) {
                var error = errorList[i];
                $("#errorMessage").prepend('<li>'+error+'</li>');
            };
        }
        if (undefined != action.displayInDiv) {
/*
            if (tinyMCE) {
                tinyMCE.triggerNodeChange();
            }
*/
            $("#"+action.displayInDiv[0]).load(action.displayInDiv[1]);
/*
            if (tinyMCE) {
                tinyMCE.triggerNodeChange();
            }
*/
        }
        if (undefined != action.callback) {
            var callback = eval(action.callback);
            callback.apply(this,[response]);
        }
        this.onToServiceShutdownCallback();
    },

    onControllerEvent: function() {
        return true;
    },

    _onControllerEvent: function() {
        if (this.onControllerEvent() && this.onToServiceStartupCallback()) {
            var model = this.model;
            //Kitpages.log.debug("_onControllerEvent testString="+this.testString);
            model.toService(this);
        }
    },

    onToServiceStartupCallback: function() {
        if (this.isToServiceRunning==false) {
            this.isToServiceRunning = true;
            return true;
        }
        return false;
    },
    onToServiceShutdownCallback: function() {
        this.isToServiceRunning = false;
    }

});

Kitpages.mvc.FormController = Kitpages.mvc.Controller.extend({
    constructor: function(model, elementId, eventNameWithoutOn, onResultAction) {
        //Kitpages.log.debug("init Controller initValue="+elementId+" event="+eventNameWithoutOn);
        $("#"+elementId).submit(function() {return false;});
        this.base(model, elementId, eventNameWithoutOn, onResultAction);
    }
});

Kitpages.mvc.UploadController = Kitpages.mvc.Controller.extend({
    constructor: function(model, elementId, eventNameWithoutOn, onResultAction) {
        //Kitpages.log.debug("init Controller initValue="+elementId+" event="+eventNameWithoutOn);
        $("#"+elementId).submit(function() {return false;});
        this.base(model, elementId, eventNameWithoutOn, onResultAction);
    }
});

////
// progress bar management
////

Kitpages.util.ProgressBarManager = Base.extend ({
    constructor: function(progressBarId) {
        Kitpages.util.progressBarManagerInstance = this;
        this.progressBarId = progressBarId;
        $(this).ajaxStart(Kitpages.util.progressBarManagerInstance.showProgressBar);
        $(this).ajaxStop(Kitpages.util.progressBarManagerInstance.hideProgressBar);
        this.hideProgressBar();
    },
    showProgressBar: function() {
        var instance = Kitpages.util.progressBarManagerInstance;
        $("#"+instance.progressBarId).show();
    },
    hideProgressBar: function() {
        var instance = Kitpages.util.progressBarManagerInstance;
        $("#"+instance.progressBarId).hide();
    },
    modalShowProgressBar: function() {
        var body = document.body;
        $(body).append('<div id="modalProgressBar"><img src="progressBar.gif"></div>');
    },
    modalHideProgressBar: function() {
        var instance = Kitpages.util.progressBarManagerInstance;
        $("#"+instance.progressBarId).hide();
    }
});

$(document).ready(function(){
    var toto = new Kitpages.util.ProgressBarManager("progressBar");
});
Kitpages.log.debug("Kitpages.js loaded");

