/**
 * JS FILE: com.lovelysystems.js
 * @author haudum
 * @copyright Lovelysystems AG
 *
 */

var ls = {
    VERSION : "0.1",
    AUTHOR : "Lovelysystems AG",
    DEBUG : false,
    debug : function() {
        if (this.DEBUG) {
            console.log(arguments);
        }
    }
};



/****************************************
 * ls.AjaxEvent
 * @author haudum
 ****************************************/

ls.AjaxEvent = function(type,data){
    this.type = type;
    this.data = (data) ? data : null;
    this.target = null;
};



/****************************************
 * ls.Delegate
 * @author wolf
 ****************************************/

ls.Delegate = {
    context : null,
    delegations : [],
    create : function(obj, func, data) {
        var delegation = new ls.Delegation(obj, func, data);
        this.delegations.push(delegation);
        return delegation;
    },
    destroy : function() {
        for (var i=0; i<this.delegations.length; i++) {
            this.delegations[i].destroy();
            this.delegations[i] = null;
        }
        this.delegations = null;
        delete this.delegations;
    }
};



/****************************************
 * ls.Delegation
 * @author wolf
 ****************************************/

ls.Delegation = callableType(function(obj, func, data) {
        this.obj = obj;
        this.func = func;
        this.data = data;
        this.__call__ = function() {
            var args = ls.LovelyUtils.createArgumentsArray(arguments);
            args.unshift(this.data);
            this.func.apply(this.obj, args);
        };
        this.destroy = function() {
            this.obj = null;
            this.func = null;
            this.data = null;
            delete this.obj;
            delete this.func;
            delete this.data;
        };
    });



/****************************************
 * ls.EventDispatcher
 * @author wolf
 ****************************************/

ls.EventDispatcher = function(){
    this.EventDispatcher();
};
ls.EventDispatcher.prototype.EventDispatcher = function(){
    this.DEBUG = false;
    this.listeners = {};
    this.once = {};
    this.unique = {};
};
ls.EventDispatcher.prototype.addEventListener = function(event,callback,weight) {
    if (typeof(event) != "string") {
        if (this.DEBUG) console.warn("Could not register Event "+event);
        return;
    }
    if (!this.listeners[event]) this.listeners[event] = [];
    var info = {"callback":callback};
    this.listeners[event].push(info);
    if (weight) {
        this.listeners[event].sort(function(a, b) { return a.weight-b.weight; });
    }
};
ls.EventDispatcher.prototype.removeEventListener = function(id) {
    if (!id)  return;
    var e = id.split('-')[0];
    var i = parseInt(id.split('-')[1],10);
    if (!this.listeners[e]) return;
    var spliced = this.listeners[e].splice(i, 1);
    if (spliced.length==1) {
        return true;
    } else {
        return false;
    }
};
ls.EventDispatcher.prototype.dispatchEvent = function(event) {
    var stack = this.listeners[event.type];
    if (stack) {
        for (var i=0; i<stack.length; i++) {
            if (this.DEBUG) console.log("CALLBACK",i,stack[i].callback, event.data);
            stack[i].callback.call(this, event.data);
        }
    }
    this.clearOnce(event);
};
ls.EventDispatcher.prototype.addEventOnce = function(event, callback, weight) {
    if (!this.once[event]) this.once[event] = [];
    var id = this.addEventListener(event, callback, weight);
    this.once[event].push(id);
    return id;
};
ls.EventDispatcher.prototype.unique = function(event, key, callback, weight) {
    if (!this.unique[event]) this._unique[event] = {};
    if (this.unique[event][key]) this.removeEventListener(this.unique[event][key]);
    var id = this.addEventListener(event, callback, weight);
    this.unique[event][key] = id;
};
ls.EventDispatcher.prototype.clearOnce = function(event) {
    if (!this.once[event]) return;
    for (var i=0; i<this._once[event].length;i++) {
      this.unregister(this._once[event][i]);
    }
    delete this.once[event];
};



/****************************************
 * ls.Document Singleton
 * @author haudum
 * extends ls.EventDispatcher
 ****************************************/

ls.Document = {};
makeDispatchable(ls.Document);



/****************************************
 * ls.LovelyUtils Singleton
 * @version 0.2
 * @author haudum
 ****************************************/

ls.LovelyUtils = {
    DEBUG : false,
    compileString : function(string, dict) {
        var string = unescape(string);
        for (var p in dict) {
            var re = new RegExp('\\${'+p+'}', 'g');
            string = string.replace(re, dict[p]);
        }
        return string;
    },
    equal : function(obj1, obj2) {
        if (!obj1 && obj2) return false;
        if (obj1 && !obj2) return false;

        var equal = true;
        for (p in obj1) {
            if (obj1[p] != obj2[p]) return false;
        }
        return equal;
    },
    equalArr : function(arr1, arr2) {
        if (arr1.length != arr2.length) return false;
        equal = true;
        for (var i=0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i]) return false;
        }
        return equal;
    },
    bool : function(obj) {
      if (typeof(obj) == 'object') {
        for (var p in obj) return true;
        return false;
      }
      return Boolean(obj);
    },
    regMap : function(str, map) {
      for (var name in map) if (str.match(map[name])) return name;
    },
    createArgumentsArray : function(args) {
      var arr = [];
      for (var i=0; i<args.length;i++) {
        arr[i]=args[i];
      }
      return arr;
    },
    scrollToElement : function(elementId, yoffset) {
        var yoffset = (yoffset) ? yoffset : 0;
        var element = document.getElementById(elementId);
        var scrollY = 0;
        while (element != null){
            scrollY += element.offsetTop;
            element = element.offsetParent;
        }
        window.scrollTo(0, scrollY+yoffset);
    },
    scrollToNode : function(element) {
        // if element is a jQuery object use its first element
        var element = element.length ? element[0] : element;
        var scrollY = 0;
        while (element != null){
            scrollY += element.offsetTop;
            element = element.offsetParent;
        }
        var clientPosY = window.pageYOffset || document.documentElement.scrollTop;
        if (scrollY<clientPosY) {
            window.scrollTo(0, scrollY);
        }
    },
    convertTimestamp : function(timestamp) {
        var date = new Date(timestamp);
        var day  = (date.getDate().toString().length == 1) ? "0"+date.getDate() : date.getDate();
        var month = (date.getMonth().toString().length == 1) ? "0"+date.getMonth() : date.getMonth();
        var year = date.getFullYear();
        var hours = (date.getHours().toString().length == 1) ? "0"+date.getHours() : date.getHours();
        var seconds = (date.getMinutes().toString().length == 1) ? "0"+date.getMinutes() : date.getMinutes();
        return day+"."+month+"."+year+" "+hours+":"+seconds+" Uhr";
    },
    loadAjaxContent : function(url,target,opt) {
        console.info("THIS FUNCTION IS DEPRECATED AND IS GOING TO REMOVE TROUGH zl.AjaxLoader");
        $("#loader-image").show();
        if (!url || !target) {
            ls.debug("No url or target.");
            return false;
        }
        var target = $(target);
        if (target.length < 0 || target.length > 1) {
            ls.debug("No or too many targets.");
            return false;
        }
        if (!target.parent().hasClass("ajax-wrapper")) {
            var wrapper = "<div id=\"${id}\" class=\"${class}\"></div>";
            wrapper = ls.LovelyUtils.compileString(wrapper,{"id" : "ajax-wrapper-"+new Date().getTime(),
                                                            "class" : "ajax-wrapper"});
            target.wrap(wrapper);
        }
        target.parent().load(url, ls.Delegate.create(this,
                                                     this.onAjaxLoadComplete,
                                                     opt));
    },
    onAjaxLoadComplete : function(data,context,response) {
        $("#loader-image").hide();
    },
    parseQueryString : function(string,type,mapping,html){
        var html = (html) ? html : false;
        var type = (type) ? type : 'dict';
        var mapping = (mapping) ? mapping : [];

        if (typeof string === "string" && string != "") {
            var obj = {};
            var keywords = {};
            var pairs = string.split("&");
            if (pairs) {
                for (var i=0; i<pairs.length; i++) {
                    var p = pairs[i].split("=");
                    if (p.length < 2) {
                        console.log(string + " is not a valid query string to parse");
                        return {};
                    }
                    var value = decodeURIComponent(p[1].replace(/\+/g,"%20"));
                    value = value.replace(/<script\b[^>]*>(.*?)<\/script>/i,"");
                    if (!html) value = value.replace(/<[a-zA-Z\/][^>]*>/g,"");
                    var key = p[0];
                    for(var j = 0; j<mapping.length; j++){
                        if(key == mapping[j]){
                            keywords[key] = value;
                        }
                    }
                    obj[key] = value;
                    if (obj[key] === "True" || obj[key] === "true") {
                        obj[key] = true;
                    } else if (obj[key] === "False" || obj[key] === "false") {
                        obj[key] = false;
                    }
                }
            }
            if (this.DEBUG) console.log("converter: ",string,obj);

            var keywordcounter = 0;
            for(key in keywords){
                keywordcounter++;
                delete obj[key];
            }
            var wrapper = {};
            if(type == "dict"){
                if(keywordcounter > 0){
                    wrapper = obj;
                    for(key in keywords){
                        wrapper[key] = keywords[key];
                    }
                    return wrapper;
                }else{
                    return obj;
                }
            }else if(type =="data"){
                if(keywordcounter > 0){
                    wrapper['data'] = obj;
                    for(key in keywords){
                        wrapper[key] = keywords[key];
                    }
                    return wrapper;
                }else{
                    wrapper['data'] = obj;
                    return wrapper;
                }
            }else{
                return null;
            }
        } else {
            return {};
        }
    },
    ajaxRPC : function(endpoint,method,data,mapping){
        if(!endpoint){
            console.info('ajaxRPC(endpoint,method,{data},[mapping])');
            return;
        }
        var proxy = new ls.JsonRPC(endpoint);
        proxy.addEventListener(events.RPCEvent.SUCCESS,
                               ls.Delegate.create(this,
                                                  this.onAjaxRPCComplete,
                                                  mapping));
        proxy.call(method,data);
    },
    onAjaxRPCComplete : function(mapping,context,response){
        if(response != 'None'){
            for(var i=0;i<mapping.length;i++){
                var node = mapping[i]['target'];
                var field = mapping[i]['field'];
                var defaultTxt = mapping[i]['defaultTxt'];
                var res = response[field] != null ? response[field] : defaultTxt;
                node.empty().append(res);
            }
        }else{
            console.log("Nothing came back from RPC");
        }
    }
};




/****************************************
 * ls.BatchBox
 * @author haudum
 * @extends ls.EventDispatcher
 ****************************************/

ls.BatchBox = function(node, params){
    this.EventDispatcher();
    this.BatchBox(node, params);
};

ls.BatchBox.prototype.BatchBox = function(node, params){
    this.DEBUG = false;
    this.CLASS = "ls.BatchBox";
    this.context = node;
    this.params = params;
};

ls.BatchBox.prototype.bindClickEvents = function(){
    var buttons = $("a.ajaxBatchLink", this.context);
    buttons.bind("click", ls.Delegate.create(this,
                                             this.getBatchURL,
                                             null));
};

ls.BatchBox.prototype.getBatchURL = function(data,context){
    var url = context.attr("href");
    context.attr("href","javascript:void(0)");
    var INVALID_PATTERN = new RegExp(/None$/);
    if (!url || url.match(INVALID_PATTERN) || url == "javascript:void(0)") {
        if (this.DEBUG) console.warn("No valid URL specified.");
        context.unbind("click");
        return;
    }
    this.dispatchEvent(new ls.AjaxEvent(events.BatchEvent.INIT, url));
    this.loadBatch(url);
};

ls.BatchBox.prototype.loadBatch = function(data,context) {
    var url = data;
    this.dispatchEvent(new ls.AjaxEvent(events.BatchEvent.LOAD, url));
    this.getBatchContainer().load(url, ls.Delegate.create(this,
                                                          this.onBatchLoaded,
                                                          null));
};

ls.BatchBox.prototype.onBatchLoaded = function(data,context) {
    this.context = context;
    ls.AjaxCommands.init(context);
    this.dispatchEvent(new ls.AjaxEvent(events.BatchEvent.COMPLETE, null));
};

ls.BatchBox.prototype.getBatchContainer = function(){
    var div = "<div class='batchContainer'></div>";
    if (!this.context.parent().hasClass("batchContainer")) {
        this.context.wrap(div);
    }
    return this.context.parent();
};

inheritClass(ls.BatchBox, ls.EventDispatcher);


/****************************************
 * ls.RecaptchaManager Singleton
 * @author haudum
 * @extends ls.EventDispatcher
 ****************************************/

ls.RecaptchaManager = {
    DEBUG : false,
    API : "http://api.recaptcha.net/js/recaptcha_ajax.js",
    KEY : null,
    template : "/__recaptcha_base__",
    currentId : null,
    context : null,
    docs : "http://recaptcha.net/apidocs/captcha/client.html",
    isAPILoaded : true,

    setKey : function(key){
        this.KEY = key;
    },

    setTemplate : function(url){
        this.template = url;
    },

    initCaptcha : function(id, template) {
        if (this.DEBUG) console.log(id,template,this.isAPILoaded);
        if (!this.KEY) {
            console.warn("No Recaptcha key set!");
            return;
        }
        if (!this.isAPILoaded) {
            $.getScript(this.API, ls.Delegate.create(this,
                                                     this.onAPIReady,
                                                     {"id":id,"template":template}));
        } else {
            if (this.DEBUG) console.log(this.currentId, id);
            if (this.currentId && this.currentId != id) {
                Recaptcha.destroy();
                this.dispatchEvent(new ls.AjaxEvent(events.CaptchaEvent.INIT, null));
                $("#recaptcha_widget_"+this.currentId).empty();
     	        $("#recaptcha_widget_"+this.currentId).attr("id",this.currentId);
                $("#"+this.currentId).hide();
            }
            if (this.currentId != id) {
                this.context = $("#"+id);
                this.currentId = id;
                this.loadTemplate(template);
            } else {
                if (this.DEBUG) console.log("same captcha id: ",this.currentId,id);
            }
        }
    },

    onAPIReady : function(data,context,event) {
        if (this.DEBUG) console.log("ReCaptcha API loaded.");
        this.isAPILoaded = true;
        this.initCaptcha(data.id,data.template);
    },

    loadTemplate : function(template) {
        var tpl = template ? template : this.template;
        this.getTarget().load(tpl, ls.Delegate.create(this,
                                                      this.createCaptcha,
                                                      null));
    },

    createCaptcha : function(data,context,response){
        Recaptcha.create(this.KEY,
                         this.currentId,
                         {theme: 'custom',
                          tabindex: 0,
                          lang: 'de',
                          custom_theme_widget : 'recaptcha_widget_' + this.currentId });
    },

    reloadCaptcha : function() {
        Recaptcha.reload();
    },

    destroyCaptcha : function() {
        if (typeof Recaptcha === "undefined") return;
        Recaptcha.destroy();
        this.currentId = null;
    },

    getTarget : function(){
        var div = "<div class='captchaContainer' id='recaptcha_widget_"+this.currentId+"'></div>";
        if (!this.context.parent().hasClass("captchaContainer")) {
            this.context.wrap(div);
        }
        return this.context.parent();
    },

    showHelp : function(){
        console.log("Show help.");
    }
};

makeDispatchable(ls.RecaptchaManager);



/****************************************
 * ls.TabBox
 * @author haudum
 * @extends ls.EventDispatcher
 ****************************************/

ls.TabBox = function(node,params){
    this.EventDispatcher();
    this.TabBox(node,params);
};

ls.TabBox.prototype.TabBox = function(node,params){
    this.context = node;
    this.params = params;
    this.TAB_PREFIX = "tab";
    this.BOX_PREFIX = "box";
    this.BOX_SUFFIX = "Content";
    this.CLASS_PREFIX = "show";
    this.tabs = $("div."+this.TAB_PREFIX, node);
    this.boxes = $("div."+this.BOX_PREFIX + this.BOX_SUFFIX, node);
    this.oldTabClass = this.CLASS_PREFIX + params["activetab"];
};

ls.TabBox.prototype.bindEvents = function(){
    this.tabs.bind("click", ls.Delegate.create(this,
                                               this.switchToTab,
                                               null));
};

ls.TabBox.prototype.switchToTab = function(data, context, event){
    var tab = context.attr("id").split(this.TAB_PREFIX)[1];
    var boxName = this.BOX_PREFIX + tab + this.BOX_SUFFIX;
    var content = $("#"+boxName, this.context);
    this.boxes.hide();
    content.show();
    var newTabClass = this.CLASS_PREFIX + tab;
    this.context.removeClass(this.oldTabClass);
    this.context.addClass(newTabClass);
    this.oldTabClass = newTabClass;
    this.dispatchEvent(new ls.AjaxEvent(events.TabEvent.SWITCH, tab));
};

inheritClass(ls.TabBox, ls.EventDispatcher);


/****************************************
 * ls.OverlayManager Singleton
 * @author haudum
 * @extends ls.EventDispatcher
 ****************************************/

ls.OverlayManager = {
    DEBUG : true,
    isOpen : false,
    context : null,
    params : null,
    holder : $("#overlay"),
    content : $("#overlay-content", this.holder),
    tableClass : "overlayBox",
    garbage : [],

    setOverlay : function(holderId,contentId) {
        if (!holderId || !contentId) {
            return;
        } else {
            this.holder = $("#"+holderId);
            this.content = $("#"+contentId, this.holder);
            $(".overlayClose", this.holder).bind("click", ls.Delegate.create(this,
                                                                             this.closeOverlay,
                                                                             null));
        }
    },

    initOverlay : function(node, params) {
        var url = params["url"];
        if (!url) {
            if (this.DEBUG) console.warn("No URL for overlay spezified.");
            node.attr("href","javascript:void(0)");
            return;
        }
        var size = params["class"];
        if (!size) {
            if (this.DEBUG) console.log("No overlay class spezified. Take default");
            size = "smallBox";
        }
        this.context = node;
        this.params = params;
        this.dispatchEvent(new ls.AjaxEvent(events.OverlayEvent.INIT, null));
        this.openOverlay(url,size);
    },

    openOverlay : function(url,data) {
        if (!isIE) this.fixIframes('hidden');
        $("object").css("visibility","hidden");
        var data = data || null;
        var h = $(document).height();
        var top = document.documentElement.scrollTop;
        $("#overlayBackground").css("height", h);
        $("#overlayBackgroundIFrame").css("height", h);
        $("#overlay-content").css("top",top+50);
        this.holder.toggle();
        this.isOpen = true;
        this.dispatchEvent(new ls.AjaxEvent(events.OverlayEvent.LOAD, data));
        this.content.load(url, ls.Delegate.create(this,
                                                  this.onOverlayComplete,
                                                  null));
    },

    switchOverlay : function(url, data) {
        if (this.isOpen) {
            this.dispatchEvent(new ls.AjaxEvent(events.OverlayEvent.LOAD, data));
            this.content.load(url, ls.Delegate.create(this,
                                                      this.onOverlayComplete,
                                                      null));
        } else {
            console.log("No open overlay!");
        }
    },

    onOverlayComplete : function(data,context,result) {
        $(document).bind("keypress", ls.Delegate.create(this,
                                                        this.onKeyPress,
                                                        null));
        this.dispatchEvent(new ls.AjaxEvent(events.OverlayEvent.COMPLETE, null));
    },

    closeOverlay : function() {
        $(document).unbind("keypress");
        if (!isIE) this.fixIframes('visible');
        $("object").css("visibility","visible");
        this.holder.toggle();
        this.content.empty();
        this.isOpen = false;
        this.dispatchEvent(new ls.AjaxEvent(events.OverlayEvent.CLOSE, null));
    },

    onKeyPress : function(data,context,event) {
        if (event.which == 0) {
            //this.closeOverlay();
        };
    },

    fixIframes : function(cssStyle){
        window.setTimeout(function(){
            var iframes = document.getElementsByTagName('iframe');
            for (var i=0; i<iframes.length; i++) {
                iframes[i].style.visibility = cssStyle;
            }
        }, 250);
    }

};

makeDispatchable(ls.OverlayManager);



/****************************************
 * ls.TemplateParser
 * @author haudum
 ****************************************/

ls.TemplateParser = function(node){
    this.TemplateParser(node);
};

ls.TemplateParser.prototype.TemplateParser = function(node){
    this.fade = false;
    this.context = node;
    this.html = this.context.html();
    this.context.empty();
};

ls.TemplateParser.prototype.parseTemplate = function(obj, pos, node){
    var obj = obj ? obj : {};
    var pos = pos ? pos : "append";
    var node = node ? node : this.context;
    var html = ls.LovelyUtils.compileString(this.html, obj);
    if (pos == "prepend") {
        if (this.fade) {
            var tmp = $(html);
            tmp.hide();
            node.show();
            node.prepend(tmp);
            tmp.fadeIn("slow");
        } else {
            node.prepend(html).show();
        }
    } else if (pos == "append") {
        if (this.fade) {
            var tmp = $(html);
            tmp.hide();
            node.append(tmp);
            tmp.fadeIn("slow");
        } else {
            node.append(html).show();
        }
    }
};

ls.TemplateParser.prototype.clearNode = function(str){
    if (str) {
        this.context.empty().append(str);
    } else {
        this.context.empty();
    }
};


/****************************************
 * ls.SearchPanel Singleton
 * @author haudum
 ****************************************/

ls.SearchPanel = {
    url : "",
    context : null,
    input : null,
    button : null,

    init : function(node,params) {
        var url = params.url;
        if (url) this.url = url;

        this.input = $(params.button, node);
        this.input.bind("click", ls.Delegate.create(this,
                                                    this.submitQuery,
                                                    "click"));
        this.button = $(params.input, node);
        this.button.bind("keydown", ls.Delegate.create(this,
                                                       this.onKeyDown,
                                                       "enter"));
    },

    setURL : function(url) {
        if (!url) return;
        this.url = url;
    },

    onKeyDown : function(data,context,event) {
        if (!event) return;
        if (event.which == 13) {
            this.submitQuery();
        }
    },

    submitQuery : function(data,context,event) {
        var query = this.input.val();
        if (query == "" || query == " ") {
            ls.Debug.log("No input.");
            return;
        } else {
            window.location.href = this.url + "/" + query;
        }
    }
};


/****************************************
 * ls.JsonRPC
 * @author haudum
 * @extends ls.EventDispatcher
 * @description creates a JSON-RPC proxy
 ****************************************/

ls.JsonRPC = function(endpoint,host){
    this.EventDispatcher();
    this.JsonRPC(endpoint,host);
};

ls.JsonRPC.prototype.JsonRPC = function(endpoint,host){
    this.endpoint = endpoint;
    this.host = host ? host : GLOBALS.HOSTNAME;
    this.url = this.host + this.endpoint;
};

ls.JsonRPC.prototype.call = function(method,params){
    if (!typeof params === "object") return;
    var id = Math.floor(Math.random() * 1000000);
    var data = new Object();
    data.method = method;
    data.id = id;
    data.version = "1.1";
    data.params = params;
    if (this.endpoint) {
        var jsonData = JSON.stringify(data);
        $.post(this.url, jsonData, ls.Delegate.create(this,
                                                      this.onResponse,
                                                      null));
    } else {
        console.log("No endpoint");
    }
};

ls.JsonRPC.prototype.onResponse = function(data,context,responseString){
    var response = JSON.parse(responseString);
    this.dispatchEvent(new ls.AjaxEvent(events.RPCEvent.RESPONSE, response));
    if (response.result) {
        console.log("JSON-RPC/Response: ", response.result);
        this.dispatchEvent(new ls.AjaxEvent(events.RPCEvent.SUCCESS, response.result));
    } else if (response.result == false) {
        console.log("JSON-RPC/Response: ", response.result);
        this.dispatchEvent(new ls.AjaxEvent(events.RPCEvent.FAIL, response.error));
    } else if (response.error) {
        var report = {};
        if (response.error.message.match(/'(\w+)'/)) {
            var err = response.error.message.match(/'(\w+)'/)[1];
            report[err] = response.error.message;
        }
        if (response.error.message.match(/old_pass/)) {
            report["old_password"] = "old_password";
        }
        if (response.error.message.match(/Invalid Captcha/)) {
            report["recaptcha_response_field"] = "error_captcha_invalid";
        }
        if (response.error.type.match(/zlapp.user.NoSuchUser/)) {
            report["email"] = "email";
        }
        if (response.error.type.match(/zlapp.user.UserExists/)) {
            report["email-already-taken"] = "email-already-taken";
        }
        console.log("JSON-RPC/Error/Message: ", response.error.message);
        console.log("JSON-RPC/Error/Type: ", response.error.type);
        this.dispatchEvent(new ls.AjaxEvent(events.RPCEvent.FAIL, report));
    }
};

inheritClass(ls.JsonRPC, ls.EventDispatcher);



/***********************************
 * Upload Widget for AWS/GAE
 * uses JSON-RPC
 ***********************************/

ls.AWSUploader = function(node){
    this.EventDispatcher();
    this.AWSUploader(node);
};

ls.AWSUploader.prototype.AWSUploader = function(node){
    this.DEBUG = false;
    this.context = node;
    this.wid = this.context.attr("id") || "noIdForm";
    this.params = this.context.getNSParams("ajax");
    this.action = null;
    this.FIELD = "<input id='${f_id}' type='hidden' name='${f_name}' value='${f_value}' />";
};

ls.AWSUploader.prototype.requestPolicy = function(){
    if (!this.params.endpoint ||
        !this.params.method ||
        !this.params.purpose) {
        console.warn("Could not request policy. Parameters missing.");
        return;
    }
    var proxy = new ls.JsonRPC(this.params.endpoint);
    proxy.addEventListener(events.RPCEvent.SUCCESS,
                           ls.Delegate.create(this,
                                              this.onPolicy,
                                              null));
    proxy.call(this.params.method,{"purpose":this.params.purpose});
};

ls.AWSUploader.prototype.onPolicy = function(data,context,response){
    this.action = response.action;
    var fields = response.fields;
    this.additionalFields = fields;
    for (var i=fields.length-1; i>=0; i--) {
        var fieldName = fields[i][0];
        var fieldValue = fields[i][1];
        var fieldId = this.wid + "_" + fieldName;
        this.context.prepend(ls.LovelyUtils.compileString(this.FIELD,{"f_name":fieldName,"f_value":fieldValue,"f_id":fieldId}));
    }
    this.uploadFile();
};

ls.AWSUploader.prototype.uploadFile = function(){
    var data = this.context.formSerialize();
    this.context.attr("action",this.action);
    this.context.ajaxSubmit(ls.Delegate.create(this,
                                               this.onUploadComplete,
                                               null));
};

ls.AWSUploader.prototype.onUploadComplete = function(data,context,response){
    this.removeAdditionalField();
    response = response.replace(/<script\b[^>]*>(.*?)<\/script>/i,"");
    console.log("response:",response.trim());
    var result = JSON.parse(response.trim());
    var fileData = result.result;
    console.log("filedata",fileData);
    if (result.result != false) {
        this.dispatchEvent(new ls.AjaxEvent(events.AjaxEvent.SUCCESS, fileData));
    } else {
        this.dispatchEvent(new ls.AjaxEvent(events.AjaxEvent.FAIL, result));
    }
};

ls.AWSUploader.prototype.removeAdditionalField = function(){
    var fields = this.additionalFields;
    for (var i=0; i<fields.length; i++) {
        var fieldName = fields[i][0];
        var fieldId = this.wid + "_" + fieldName;
        $("#"+fieldId).remove();
    }
};

inheritClass(ls.AWSUploader, ls.EventDispatcher);


ls.StorageManager = {
    getDomain : function(){
        return window.location.hostname.replace(/\./g,"");
    },
    getWindowData : function(){
        var data = {};
        try {
            data = (window.name != "") ? JSON.parse(window.name) : {};
        } catch (e) {
            console.log(e)
            console.log("window.name is empty or malformed JSON");
            window.name = "{}";
        }
        return data;
    },
    getData : function() {
        var ns = this.getDomain();
        var win = this.getWindowData();
        return win[ns] ? win[ns] : {};
    },
    addData : function(key,val){
        var win = this.getWindowData();
        var ns = this.getDomain();
        if (!win[ns]) win[ns] = {};
        win[ns][key] = val;
        console.log(win);
        window.name = JSON.stringify(win);
    }
}

