var serviceURLBase = 'http://api.bigstage.com/api/';
//var serviceURLBase = 'http://localhost:8080/py/api/';
var memberServiceURL = serviceURLBase + 'MemberService.json';
var VFSServiceURL = serviceURLBase + 'VirtualFileSystemService.json';
var templateServiceURL = serviceURLBase + 'TemplateService.json';
var actorServiceURL = serviceURLBase + 'ActorService.json';
var renderServiceURL = serviceURLBase + 'RenderService.json';

function createPortableYouJSONRequestData(method, paramString) {
    return '{"method": "' + method + '", "params": [' + paramString + '], "id":0, "jsonrpc":"2.0" }';
}

function sendPortableYouJSONRequest(serviceURL, jsonData, callback) {
    new Ajax.Request('http://deadspaceworld.com/proxy.php', {
        parameters: { serviceURL: serviceURL, jsonData: jsonData},
        onSuccess: function(transport) {
            callback(transport.responseJSON);
        },
        onFailure: function() {
            return 'failure';
        }
    });
}

var MemberService = {
    createMemberParams: function(emailAddress, password) {
        var params = new Object();
        params.emailAddress = emailAddress;
        params.password = password;
        return params;
    },
    createMember: function(memberParams, callbackFunction) {
        if (RealTypeOf(memberParams).toLowerCase() != 'object') {
            alert('Parameter memberParams of function createMember must be of type Object, aborting call');
            return;
        }
        var data = createPortableYouJSONRequestData('createMember', Object.toJSON(memberParams));
        sendPortableYouJSONRequest(memberServiceURL, data, callbackFunction);
    },
    getMemberByGlobalId: function(globalId, callbackFunction) {
    },
    getMemberByEmailAddress: function(username, callbackFunction) {
        var data = createPortableYouJSONRequestData('getMemberByEmailAddress', '"' + username + '"');
        sendPortableYouJSONRequest(memberServiceURL, data, callbackFunction);
    },
    isExistingMember: function(username, callbackFunction) {
        var data = createPortableYouJSONRequestData('isExistingMember', '"' + username + '"');
        sendPortableYouJSONRequest(memberServiceURL, data, callbackFunction);
    },
    isActivatedMember: function(username, callbackFunction) {
        var data = createPortableYouJSONRequestData('isActivatedMember', '"' + username + '"');
        sendPortableYouJSONRequest(memberServiceURL, data, callbackFunction);
    },
    authenticateMember: function(username, password, callbackFunction) {
        var data = createPortableYouJSONRequestData('authenticateMember', '"' + username + '", "' + password + '"');
        sendPortableYouJSONRequest(memberServiceURL, data, callbackFunction);
    }

};

var TemplateService = {
    getVideoTemplates: function(startIndex, numberOfObjects, callbackFunction) {
        var data = createPortableYouJSONRequestData('getVideoTemplates', '"' + startIndex + '", "' + numberOfObjects + '"');
        sendPortableYouJSONRequest(templateServiceURL, data, callbackFunction);
    },
    getImageTemplates: function(startIndex, numberOfObjects, callbackFunction) {
        var data = createPortableYouJSONRequestData('getImageTemplates', '"' + startIndex + '", "' + numberOfObjects + '"');
        sendPortableYouJSONRequest(templateServiceURL, data, callbackFunction);
    },
    getVideoTemplateByGlobalId: function(globalId, callbackFunction) {
        var data = createPortableYouJSONRequestData('getVideoTemplateByGlobalId', '"' + globalId + '"');
        sendPortableYouJSONRequest(templateServiceURL, data, callbackFunction);
    },
    getImageTemplateByGlobalId: function(globalId, callbackFunction) {
        var data = createPortableYouJSONRequestData('getImageTemplateByGlobalId', '"' + globalId + '"');
        sendPortableYouJSONRequest(templateServiceURL, data, callbackFunction);
    }
};

var ActorService = {
    createActorParamsOnePhoto: function(image1GlobalId, gender) {
       var params = new Object();
       params.sourceImages = new Array();
       params.sourceImages[0] = image1GlobalId;
       params.gender = gender;
       return params;
   },
    createActorParamsThreePhotos: function(image1GlobalId, image2GlobalId, image3GlobalId, gender) {
        var params = new Object();
        params.sourceImages = new Array();
        params.sourceImages[0] = image1GlobalId;
        params.sourceImages[1] = image2GlobalId;
        params.sourceImages[2] = image3GlobalId;
        params.gender = gender;
        return params;
    },
    createActor: function(actorParams, callbackFunction) {
        if (RealTypeOf(actorParams).toLowerCase() != 'object') {
            alert('Parameter actorParams of function createActor must be of type Object, aborting call');
            return;
        }
        if (actorParams.gender != 'MALE' && actorParams.gender != 'FEMALE') {
            alert('Parameter actorParams.gender must be either MALE or FEMALE (note all uppercase), aborting call');
            return;
        } 
        var data = createPortableYouJSONRequestData('createActor', Object.toJSON(actorParams));
        sendPortableYouJSONRequest(actorServiceURL, data, callbackFunction);
    },
    getActorByGlobalId: function(globalId, callbackFunction) {
        var data = createPortableYouJSONRequestData('getActorByGlobalId', '"' + globalId + '"');
        sendPortableYouJSONRequest(actorServiceURL, data, callbackFunction);
    },
    getActorByMember: function(memberGlobalId, callbackFunction) {
        var data = createPortableYouJSONRequestData('getActorByMember', '"' + memberGlobalId + '"');
        sendPortableYouJSONRequest(actorServiceURL, data, callbackFunction);
    },
    doesMemberHaveActor: function(memberGlobalId, callbackFunction) {
        alert('not implemented');
    },
    setMemberActor: function(memberGlobalId, actorGlobalId, callbackFunction) {
        alert('not implemented');
    },
    createReconstructionJobParams: function(actorGlobalId, jobPriority, callbackUrl, formatName, formatVersion) {
        var params = new Object;
        params.actorGid = actorGlobalId;
        params.priority = jobPriority;
        params.callbackUrl = callbackUrl;
        params.formatName = formatName;
        params.formatVersion = formatVersion;
        return params;
    },
    createReconstructionJob: function(reconstructionJobParams, callbackFunction) {
        if (RealTypeOf(reconstructionJobParams).toLowerCase() != 'object') {
            alert('Parameter reconstructionJobParams of function createReconstructionJob must be of type Object, aborting call');
            return;
        }
        var data = createPortableYouJSONRequestData('createReconstructionJob', Object.toJSON(reconstructionJobParams));
        sendPortableYouJSONRequest(actorServiceURL, data, callbackFunction);
    },
    createReconstructionJobBatch: function(reconstructionJobBatchParams, callbackFunction) {
        alert('not implemented');
    },
    getReconstructionJobByLocalId: function(jobLocalId, callbackFunction) {
        var data = createPortableYouJSONRequestData('getReconstructionJobByLocalId', '"' + jobLocalId + '"');
        sendPortableYouJSONRequest(actorServiceURL, data, callbackFunction);
    },
    getReconstructionJobBatchByLocalId: function(batchLocalId, callbackFunction) {
        alert('not implemented');
    },
    updateActor: function(actorGlobalId, updatedActorParams) {
        alert('not implemented');
    }
};

var VirtualFileSystemService = {
    getUploadURL: function(callbackFunction) {
        var data = createPortableYouJSONRequestData('getUploadURL', '');
        sendPortableYouJSONRequest(VFSServiceURL, data, callbackFunction);
    },
    getUploadKey: function(callbackFunction) {
        var data = createPortableYouJSONRequestData('getUploadKey', '');
        sendPortableYouJSONRequest(VFSServiceURL, data, callbackFunction);
    }
};

var RenderService = {
    createAccessoryMap: function() {
        return new Object();
    },
    addAccessoryToAccessoryMap: function(map, accessoryLocator, accessoryGlobalId) {
        map[accessoryLocator] = accessoryGlobalId;
    },
    createActorModificationParams: function(blendshapeGlobalId, weight) {
        var params = new Object();
        params.blendShapeGid = blendshapeGlobalId;
        params.weight = weight;
        return params;
    },
    createRenderJobActorParams: function(actorGlobalId, actorModificationParamsArray, accessoriesMap) {
        if ((RealTypeOf(actorModificationParamsArray)).toLowerCase() != 'array' && actorModificationParamsArray != null) {
            alert('actorModificationParamsArray (2nd parameter of function createRenderJobActorParams) must be of type Array or null');
            return null;
        }
        if ((RealTypeOf(accessoriesMap)).toLowerCase() != 'object' && accessoriesMap != null) {
            alert('accessoriesMap (3rd parameter of function createRenderJobActorParams) must be of type Object or null');
            return null;
        }
        var params = new Object();
        params.actorGid = actorGlobalId;
        params.modifications = actorModificationParamsArray;
        params.accessories = accessoriesMap;
        if (params.modifications == null) {
            params.modifications = new Array();
        }
        if (params.accessories == null) {
            params.accessories = new Object();
        }
        return params;
    },
    createRenderJobOverlayParams: function(overlayFileGlobalId, xOffset, yOffset, width, height) {
        var params = new Object();
        params.overlayFileGid = overlayFileGlobalId;
        params.x = xOffset;
        params.y = yOffset;
        params.width = width;
        params.height = height;
        return params;
    },
    createRenderJobParams: function(templateGlobalId, priority, callbackUrl, outputFormatName,
                                    renderJobActorParamsArray, renderJobOverlayParamsArray, width, height) {
        if ((RealTypeOf(renderJobActorParamsArray)).toLowerCase() != 'array') {
            alert('renderJobActorParamsArray (5th parameter of function createRenderJobParams) must be of type array');
            return null;
        }
        if ((RealTypeOf(renderJobOverlayParamsArray)).toLowerCase() != 'array' && renderJobOverlayParamsArray != null) {
            alert('renderJobActorParamsArray (6th parameter of function createRenderJobParams) must be of type array or null');
            return null;
        }
        var params = new Object();
        params.templateGid = templateGlobalId;
        params.priority = priority;
        params.callbackUrl = callbackUrl;
        params.outputFormat = outputFormatName;
        params.actors = renderJobActorParamsArray;
        params.overlays = renderJobOverlayParamsArray;
        params.width = width;
        params.height = height;
        if (params.overlays == null) {
            params.overlays = new Array();
        }
        return params;
    },
    createRenderJob: function(renderJobParams, callbackFunction) {
        if (RealTypeOf(renderJobParams).toLowerCase() != 'object') {
            alert('Parameter renderJobParams of function createRenderJob must be of type object, aborting call');
            return;
        }
        var data = createPortableYouJSONRequestData('createRenderJob', Object.toJSON(renderJobParams));
        sendPortableYouJSONRequest(renderServiceURL, data, callbackFunction);
    },
    createRenderJobBatch: function(renderJobBatchParams, callbackFunction) {

    },
    getRenderJobByLocalId: function(localId, callbackFunction) {
        var data = createPortableYouJSONRequestData('getRenderJobByLocalId', '"' + localId + '"');
        sendPortableYouJSONRequest(renderServiceURL, data, callbackFunction);
    },
    getRenderJobBatchByLocalId: function(localId, callbackFunction) {
        
    }
};

function convertObjectToJsonString(obj) {
    return Object.toJSON(obj);
}

function RealTypeOf(v) {
    if (typeof(v) == "object") {
        if (v === null) return "null";
        if (v.constructor == (new Array).constructor) return "array";
        if (v.constructor == (new Date).constructor) return "date";
        if (v.constructor == (new RegExp).constructor) return "regex";
        return "object";
    }
    return typeof(v);
}