/**
 * All content on this website (including text, images, source
 * code and any other original works), unless otherwise noted,
 * is licensed under a Creative Commons License.
 * 
 * http://creativecommons.org/licenses/by-nc-sa/2.5/
 * 
 * Copyright (C) 2010 Open-Xchange, Inc.
 * Mail: info@open-xchange.com 
 * 
 * @author Viktor Pracht <viktor.pracht@open-xchange.com>
 */

function OXMessagingMapping() {}

OXMessagingMapping.mandatoryfields = ["folder", "id"];
OXMessagingMapping.idmapping = OXMessagingMapping.stringmapping = {
    id: "id", folder: "folder", threadLevel: "threadLevel", flags: "flags",
    receivedDate: "receivedDate", colorLabel: "colorLabel", user: "user",
    size: "size", headers: "headers", body: "body", from: "from",
    subject: "subject", picture: "picture"
}

OXMessagingMapping.module="messaging/message";

OXMessagingMapping.createKeyFromData = function(array, timestamp) {
     var key = new this.objectConstructor();
     key.folder = array[0];
     key.id = array[1];
     if (timestamp) key.timestamp = timestamp;
     return key;     
}
OXMessagingMapping.createKeyFromObject = function(object) {
     var key = new this.objectConstructor();
     key.folder = object.folder;
     key.id = object.id;
     return key;
}

OXMessagingMapping.get = OXAbstractMapping.get(OXMessagingMapping);
OXMessagingMapping.execute = OXAbstractMapping.execute(OXMessagingMapping);
OXMessagingMapping.buildResponse = OXAbstractMapping.buildResponse(OXMessagingMapping);
OXMessagingMapping.criteriaRequest= OXAbstractMapping.criteriaRequest(OXMessagingMapping);
OXMessagingMapping.listRequest= OXAbstractMapping.listRequest(OXMessagingMapping);
OXMessagingMapping.addCriteriaNotInCache = OXAbstractMapping.addCriteriaNotInCache(OXMessagingMapping);
OXMessagingMapping.addCriteriaExpired = OXAbstractMapping.addCriteriaExpired(OXMessagingMapping);
OXMessagingMapping.addCriteriaMissingColumn = OXAbstractMapping.addCriteriaMissingColumn(OXMessagingMapping);
OXMessagingMapping.addListNotInCache = OXAbstractMapping.addListNotInCache(OXMessagingMapping);
OXMessagingMapping.addListExpired = OXAbstractMapping.addListExpired(OXMessagingMapping);
OXMessagingMapping.addListMissingColumn = OXAbstractMapping.addListMissingColumn(OXMessagingMapping);
OXMessagingMapping.request = OXAbstractMapping.request(OXMessagingMapping);
OXMessagingMapping.handleResponse = OXAbstractMapping.handleResponse(OXMessagingMapping);
OXMessagingMapping.handleCriteriaNotInCache = OXAbstractMapping.handleCriteriaNotInCache(OXMessagingMapping);
OXMessagingMapping.handleCriteriaExpired = OXAbstractMapping.handleCriteriaExpired(OXMessagingMapping);
OXMessagingMapping.handleCriteriaMissingColumn = OXAbstractMapping.handleCriteriaMissingColumn(OXMessagingMapping);
OXMessagingMapping.handleCriteria=OXAbstractMapping.handleCriteria(OXMessagingMapping);
OXMessagingMapping.handleListNotInCache = OXAbstractMapping.handleListNotInCache(OXMessagingMapping);
OXMessagingMapping.handleListExpired = OXAbstractMapping.handleListExpired(OXMessagingMapping);
OXMessagingMapping.handleListMissingColumn = OXAbstractMapping.handleListMissingColumn(OXMessagingMapping);
OXMessagingMapping.handleList = OXAbstractMapping.handleList(OXMessagingMapping);
OXMessagingMapping.getCollection= OXAbstractMapping.getCollection(OXMessagingMapping);
OXMessagingMapping.convertColumns = OXAbstractMapping.convertColumns(OXMessagingMapping);
OXMessagingMapping.createCacheObject = OXAbstractMapping.createCacheObject(OXMessagingMapping);
OXMessagingMapping.checkAddCriteria = OXAbstractMapping.checkAddCriteria(OXMessagingMapping);
OXMessagingMapping.checkAddEditDeleteObject= OXAbstractMapping.checkAddEditDeleteObject(OXMessagingMapping);
OXMessagingMapping.getSubCollectionsfromObject = OXAbstractMapping.getSubCollectionsfromObject(OXMessagingMapping);
OXMessagingMapping.getSubCollections = OXAbstractMapping.getSubCollections(OXMessagingMapping);
OXMessagingMapping.equalsCollection = OXAbstractMapping.equalsCollection(OXMessagingMapping);
OXMessagingMapping.errorHandler = OXCache.errorHandler;
OXMessagingMapping.deleteObjectsInternal = function(objects) {
    var tmpFn=OXCache.join.add();
    var oxMapping=OXMessagingMapping;

    // Calling all "before" callbacks.
    for(var i in OXCache.modifiedCallbacks) {
        var mc = OXCache.modifiedCallbacks[i];
        if (mc.module == oxMapping.module && mc.before) mc.before();
    }
    
    var tmpCollect=[];
    for(var mail=0;mail<objects.length;mail++) {
        var collections=oxMapping.getSubCollectionsfromObject(objects[mail],true);
        for(var count=0;count<collections.length;count++) {
            if(collections[count].check) { continue; } 
            var index=collections[count].map_objects.get(objects[mail]);
            if(index) {
                 collections[count].modified=true;
                 if(!collections[count].tmpIndexes) { collections[count].tmpIndexes=[]; }
                 collections[count].tmpIndexes.push(index);
                 tmpCollect.push(collections[count]);
                 collections[count].modifiedtmp=true;
             }               
        }
    }
    
    for(var count=0;count<tmpCollect.length;count++) {
        if(tmpCollect[count].modifiedtmp) {
            var indexes=tmpCollect[count].tmpIndexes;
            indexes.sort(function(a,b) { return a-b; });
            for(var i=indexes.length-1;i>=0;i--) {
                tmpCollect[count].objects.splice(indexes[i]-1,1);
            }
            delete tmpCollect[count].tmpIndexes;
            tmpCollect[count].map_objects=new LRUKeyList();
            for(var index=0;index<tmpCollect[count].objects.length;index++) { 
                tmpCollect[count].map_objects.set(tmpCollect[count].objects[index],index+1) 
            }
            tmpCollect[count].modifiedtmp=false;
        }
    }
    tmpFn();
}

OXMessagingMapping.deleteObjects = function(objects) {
    var oxMapping=OXMessagingMapping;
    for(var i=0;i<objects.length;i++) {
        var tmpTime=objects[i]["timestamp"]; 
        if (!tmpTime) {
            var tmpObject = OXCache.cachedObjects.get(objects[i]);
            if(tmpObject) {
                tmpTime=tmpObject.timestamp;
            }
        }
        var request = new Array();
        for (var i in objects) {
            request.push({
                module: "messaging/message", 
                action: "delete",
                folder: objects[i]["folder"],
                timestamp: objects[i]["timestamp"],
                data: { folder : objects[i]["folder"] , id : objects[i]["id"] }
            });
        }
    }
    json.put(AjaxRoot + "/multiple?session=" + session + "&continue=true",
        request, null, function(reply) {
            var tmpFn=OXCache.join.add();
            var error=new Array();
            for(var i=0;i<reply.length;i++) {
                if(reply[i].error) {
                    newServerError(reply[i]);
                    error.push(i);   
                }  
            }
            if(!error.length) { oxMapping.deleteObjectsInternal(objects); }
            tmpFn();        
        }
    );
}
OXMessagingMapping.editObjectsInternal = function(oldObjects,changes,checkExist) {
    var oxMapping=OXMessagingMapping;
    var tmpFn=OXCache.join.add();
    for(var myObject in oldObjects) {
        var tmpKeyOld=oxMapping.createKeyFromObject(oldObjects[myObject]);
        var collections=oxMapping.getSubCollectionsfromObject(oldObjects[myObject],true);
        //TODO Check Changes in Collection
        for(var i=0;i<collections.length;i++) {
            if(!collections[i].check) {
                collections[i].check=true;
            } 
        }
        for(var i in OXCache.modifiedCallbacks) {
            if(OXCache.modifiedCallbacks[i].module == oxMapping.module && !(OXCache.modifiedCallbacks[i].collection.criteria)) {
                for(var count=0;count<OXCache.modifiedCallbacks[i].collection.objects.length;count++) {
                    if(tmpKeyOld.equals(OXCache.modifiedCallbacks[i].collection.objects[count])) {
                        var mc = OXCache.modifiedCallbacks[i];
                        if (!mc.modified && mc.before) mc.before();
                        mc.modified=true;
                    }
                }
            }
        }
        var tmpObjectOld=OXCache.cachedObjects.get(tmpKeyOld);
        if(tmpObjectOld) {
           if(changes) {
              for(var i in changes) {
                  if(!checkExist || tmpObjectOld[i]!== undefined) {
                      tmpObjectOld[i]=changes[i];
                  }
              }
           }
       }
       OXCache.cachedObjects.set(tmpKeyOld,tmpObjectOld);    
    }  
    //TODO CHECK CHANGE FOLDER
    tmpFn();
}

OXMessagingMapping.editObjects = function(oldObjects,changes) {
    setTimeout(function() {
       var tmpFn=OXCache.join.add();
       OXMessagingMapping.editObjectsInternal(oldObjects,changes);
       tmpFn(); 
    },0);
}
OXMessagingMapping.createObject = function(newObject) {
    setTimeout(function() {
        var tmpFn=OXCache.join.add();
        OXMessagingMapping.createObjectsInternal([newObject]);
        tmpFn();
    },0);
}
OXMessagingMapping.createObjectsInternal = function(newObjects) {
    setTimeout(function() {
        var oxMapping=OXMessagingMapping;

        // Calling all "before" callbacks.
        for(var i in OXCache.modifiedCallbacks) {
            var mc = OXCache.modifiedCallbacks[i];
            if (mc.module == oxMapping.module && mc.before) mc.before();
        }
        
        var tmpFn=OXCache.join.add();
        for(var object in newObjects) {
            var collections=oxMapping.getSubCollectionsfromObject(newObjects[object],true);
            for(var i=0;i<collections.length;i++) {
                if(!collections[i].check) {
                    collections[i].check=true;
                }
            }
        }
        tmpFn();
    },0);
}
OXMessagingMapping.setTag = OXAbstractMapping.setTag(OXMessagingMapping);
OXCache.setMapping("messaging/message", OXMessagingMapping);

OXMessagingMapping.objectConstructor = function() {};
OXMessagingMapping.objectConstructor.createfromObject = function(o) {
    var k = new this();
    k.folder = o.folder;
    k.id = o.id;
    return k;
}
with (OXMessagingMapping.objectConstructor) {
    prototype.module = "messaging/message";
    prototype.mapping = OXMessagingMapping;
    prototype.equals = function(k) {
        return k.module == this.module && k.folder == this.folder &&
               k.id == this.id;
    };
    prototype.hashCode = function() {
        return this.folder + "/" + this.id;
    };
    prototype.hasColumns = OXAbstractObject.prototype.hasColumns;
    prototype.getColumns = OXAbstractObject.prototype.getColumns;
}