﻿/// <reference path="../External/JSON.js" />
/// <reference path="./Agility.js" />

Agility.RegisterNamespace("Agility.UGC.API");

(function(API, $) {

    //ENUMS
    API.DataType = {
        String: 0,
        TextBlob: 1,
        Int: 2,
        Double: 3,
        DateTime: 4,
        File: 5,
        GUID: 6,
        Encrypted: 7,
        Hashed: 8,
        Boolean: 9
    }

    API.RecordState = {
        New: 0,
        Published: 1,
        Deleted: 2,
        Processing: 3,
        Declined: 4,
        Error: 5,
        All: -1
    }

    API.Permission = {
        Read: 0,
        Create: 1,
        Edit: 2,
        Delete: 3,
        Moderate: 4,
        Administer: 5
    }

    API.SortDirection = {
        ASC: "ASC",
        DESC: "DESC"
    }

    API.ResponseType = {
        OK: 0,
        Error: 1
    }

    API.FileService = {
        AmazonS3: 0,
        YouTube: 1,
        Flickr: 2,
        Image: 3,
        Video: 4
    }

    API.FileServiceState = {
        New: 0,
        Unprocessed: 1,
        Processed: 2,
        Error: 3
    }

    API.FileServiceMetaDataTypeName = "JSONPFileServiceMetaData:#Agility.UGC.API.ServiceObjects";

    API.YouTubeMetaField = {
        OriginalFilePath: "OriginalFilePath",
        VideoID: "VideoID",
        Description: "Description",
        Category: "Category",
        Title: "Title",
        Keywords: "Keywords",
        Private: "Private",
        YouTubeState: "YouTubeState"
    };

    //from here: http://www.flickr.com/services/api/upload.api.html

    API.FlickrMetaField = {
        OriginalFilePath: "OriginalFilePath",
        title: "title",
        description: "description",
        tags: "tags",
        is_public: "is_public",
        is_friend: "is_friend",
        is_family: "is_family",
        safety_level: "safety_level",
        hidden: "hidden",
        photo_id: "photo_id"

        //other values are also appended as they are made available 
        /*
        secret
        photopage
        SquareImageUrl
        ThumbnailImageUrl
        SmallImageUrl
        MediumImageUrl
        LargeImageUrl
        */
    };

    API.OnInit = function(API_Url, API_AccessKey, API_Seconds, API_RandomNumber, API_ProfileRecordID, API_Hash) {
        /// <summary>
        /// Initialize the Agility DataService API
        /// </summary>
        /// <param name="API_Url" type="String">The URL to the Agility DataService REST API.</param>        
        /// <param name="API_AccessKey" type="String">The API Key.</param>
        /// <param name="API_Seconds" type="String">The # of Seconds.</param>
        /// <param name="API_RandomNumber" type="String">A Random number.</param>        
        /// <param name="API_ProfileRecordID" type="String">The current user ID.</param>        
        /// <param name="API_Hash" type="String">The API Hash.</param>        

        if (API_Url == undefined) {
            return;
        }

        API.APIUrl = API_Url;
        API.APIAccessKey = API_AccessKey;
        API.APISeconds = API_Seconds;
        API.APIRandomNumber = API_RandomNumber;
        API.APIProfileRecordID = API_ProfileRecordID;
        API.APIHash = API_Hash;

    }

    API.Record = function() {
        var ID = -1;
        var CreatedOn = function(d) { }


    }


    API.GetAllRecordTypes = function(callback) {
        /// <summary>
        /// Get All Record Types.
        /// </summary>
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        var url = _buildAPIUrl("GetAllRecordTypes", null);

        jQuery.getJSON(url, callback);

    }

    API.GetRecordType = function(recordTypeID, callback) {
        /// <summary>
        /// Get All Record Types.
        /// </summary>
        /// <param name="recordTypeID">The ID of the record type to return.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        var url = _buildAPIUrl("GetRecordType", [recordTypeID]);

        jQuery.getJSON(url, callback);

    }

    API.SaveRecordType = function(recordType, callback) {
        /// <summary>
        /// Saves a record type.
        /// </summary>
        /// <param name="recordType">The record type to save.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      


        var postData = JSON.encode(recordType);

        var url = _buildAPIUrl("SaveRecordType", null);

        _submitPostData(url, postData, callback);

    }

    API.DeleteRecordType = function(recordTypeID, callback) {
        /// <summary>
        /// Get All Record Types.
        /// </summary>
        /// <param name="recordTypeID">The ID of the record type to return.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        var url = _buildAPIUrl("DeleteRecordType", [recordTypeID]);

        jQuery.getJSON(url, callback);

    }

    API.GetRecord = function(recordID, callback) {
        /// <summary>
        /// Gets a Record.
        /// </summary>
        /// <param name="recordID">The ID of the record to return.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        var url = _buildAPIUrl("GetRecord", [recordID]);

        jQuery.getJSON(url, callback);

    }

    API.DeleteRecord = function(recordID, callback) {
        /// <summary>
        /// Deletes a Record.
        /// </summary>
        /// <param name="recordID">The ID of the record to return.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        var url = _buildAPIUrl("DeleteRecord", [recordID]);

        jQuery.getJSON(url, callback);

    }


    API.SetRecordFlag = function(recordID, flaggedYN, callback) {
        /// <summary>
        /// Sets whether a record is flagged or not.
        /// </summary>
        /// <param name="recordID">The ID of the record to return.</param>      
        /// <param name="flaggedYN">Whether the record is flagged or not.</param>      		
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        var url = _buildAPIUrl("SetRecordFlag", [recordID, flaggedYN]);

        jQuery.getJSON(url, callback);

    }

    API.SetRecordState = function(recordID, recordState, reason, callback) {
        /// <summary>
        /// Sets whether a record is flagged or not.
        /// </summary>
        /// <param name="recordID">The ID of the record to return.</param>      
        /// <param name="recordState">The State of the record (from enum)</param>      
        /// <param name="reason">The reason that the record is in this state.  May be null if not an Error state.</param>      			
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        var query = null;
        if (reason != null && reason != "") {
            query = "reason=" + escape(reason);
        }
        var url = _buildAPIUrl("SetRecordState", [recordID, recordState], query);

        jQuery.getJSON(url, callback);

    }

    API.SetRecordFileState = function(recordID, fieldName, fileServiceState, callback) {
        /// <summary>
        /// Sets the file service state on a given file service field.
        /// </summary>
        /// <param name="recordID">The ID of the record to return.</param>      
        /// <param name="fieldName">The name of the field the file is associated with on the record.</param>      
        /// <param name="fileServiceState">The fileServiceState to set the field to.  Normally this will be FileServiceState.Unprocessed.</param>      			
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        var url = _buildAPIUrl("SetRecordFileState", [recordID, fieldName, fileServiceState]);

        jQuery.getJSON(url, callback);
    }


    API.SaveRecord = function(record, callback) {
        /// <summary>
        /// Saves a record.
        /// </summary>
        /// <param name="record">The record to save.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      


        var postData = JSON.encode(record);

        var url = _buildAPIUrl("SaveRecord", null);

        _submitPostData(url, postData, callback);

    }

    API.SearchRecords = function(searchArg, callback) {
        /// <summary>
        /// Searches for records based on a SearchArg object.
        /// </summary>
        /// <param name="searchArg">The search arg object.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      


        var argStr = JSON.encode(searchArg);
        var url = _buildAPIUrl("SearchRecords");
        url += "&s=" + escape(argStr);

        jQuery.getJSON(url, callback);

    }

    var _settingsCache = null;

    API.GetSettings = function(callback, ignoreCache) {
        /// <summary>
        /// Get the Settings.
        /// </summary>
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      
        /// <param name="ignoreCache" type="Boolean">Whether to ignore the cached value and get the settings from the server every time.<param>

        if (_settingsCache == null || ignoreCache == false) {

            var url = _buildAPIUrl("GetSettings", null);

            jQuery.getJSON(url, function(data) {
                if (data.ResponseType != API.ResponseType.OK) {
                    callback(data);
                } else {
                    _settingsCache = data.ResponseData;
                    callback(data);
                }
            });
        } else {

            //use the cached value...
            callback({
                ResponseType: API.ResponseType.OK,
                ResponseData: _settingsCache
            });
        }

    }

    API.SaveSettings = function(settings, callback) {
        /// <summary>
        /// Saves the Settings
        /// </summary>
        /// <param name="settings">The settings to save.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        _settingsCache = null;

        var postData = JSON.encode(settings);

        var url = _buildAPIUrl("SaveSettings", null);

        _submitPostData(url, postData, callback);

    }

    API.GetAllSystemAccess = function(callback) {
        /// <summary>
        /// Gets all of the System Access names in the system/
        /// </summary>
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        var url = _buildAPIUrl("GetAllSystemAccess", null);

        jQuery.getJSON(url, callback);

    }

    API.GetGUID = function(callback) {
        /// <summary>
        /// Get a GUID.
        /// </summary>
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>      

        var url = _buildAPIUrl("GetGUID", null);

        jQuery.getJSON(url, callback);
    }



    API.GetAmazonS3Signature = function(policy, callback) {
        /// <summary>
        /// Deletes a file from the Amazon S3 bucket
        /// </summary>
        /// <param name="key" type="String">The full key that points to the file in S3.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>

        var url = _buildAPIUrl("GetAmazonS3Signature", null, "policy=" + escape(policy));

        jQuery.getJSON(url, callback);

    }

    API.DeleteFile = function(key, callback) {
        /// <summary>
        /// Deletes a file from the Amazon S3 bucket
        /// </summary>
        /// <param name="key" type="String">The full key that points to the file in S3.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>

        var url = _buildAPIUrl("DeleteFile", null, "key=" + escape(key));

        jQuery.getJSON(url, callback);

    }

    var _fileSizeCache = {};

    API.GetFileSize = function(key, callback) {
        /// <summary>
        /// Get the file size from a file in the Amazon S3 bucket.
        /// </summary>
        /// <param name="key" type="String">The full key that points to the file in S3.</param>      
        /// <param name="callback" type="Function">The method to callback to.  Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param>

        var url = _buildAPIUrl("GetFileSize", null, "key=" + escape(key));

        if (_fileSizeCache[key] == undefined) {
            jQuery.getJSON(url, function(data) {
                if (data.ResponseType == API.ResponseType.OK) {
                    _fileSizeCache[key] = new Number(data.ResponseData);
                }
                callback(data);
            });
        } else {
            callback({
                ResponseType: API.ResponseType.OK,
                ResponseData: new Number(_fileSizeCache[key])
            });
        }

    }



    //Osvel: added the uploadError function
    API.GetAmazonS3Form = function(options) {

        /// <summary>
        /// Builds the SWF form uploader that will upload data to Amazon S3.  The HTML will be appended to the jQuery element that is passed into the options argument (options.fieldPanel)
        /// </summary>
        /// <param name="options">The options for this input. Has the following properties: fieldName, inputID, fieldType  fieldPanel, swfUploadUrl, beforeUpload, uploadComplete, uploadError, uploadProgress, uploadButtonImageUrl, uploadButtonImageHeight, uploadButtonImageWidth, </param>        

        if (options == undefined || options == null || typeof (options) == "string") {
            throw new Error("The Amazon S3 form parameters have not been set correctly.");
        }

        var returnUrl = location.href;
        var inputID = options.inputID;
        var fieldPanel = options.fieldPanel;
        var fieldName = options.fieldName;

        var fieldType = null;


        if (options.fieldType != undefined) fieldType = options.fieldType;

        //get the settings...    
        API.GetSettings(function(data) {

            var html = null;

            if (data.ResponseType != API.ResponseType.OK) {
                html = jQuery("<span>There was an error building the " + options.fieldName + " input: " + data.Message + "</span>");
                html.appendTo(fieldPanel);
                return;
            } else {

                var settings = data.ResponseData;

                //get a new GUID
                API.GetGUID(function(dataGUID) {

                    if (dataGUID.ResponseType != API.ResponseType.OK) {
                        html = jQuery("<span>There was an error building the " + options.fieldName + " input: " + dataGUID.Message + "</span>");
                        html.appendTo(fieldPanel);
                        return;
                    } else {

                        var GUID = dataGUID.ResponseData;

                        //get the current filename stored in the field
                        var currentFileKey = $("#" + inputID).val();

                        //build the unique ids
                        var uniqueID = Agility.UniqueID("post_AmazonFileForm");
                        var uniqueFormID = uniqueID + "_form";
                        var uniqueFileUploadID = uniqueID + "_fileupload";
                        var uniqueSwfUploadID = uniqueID + "_swfupload";
                        var uniqueIFrameID = uniqueID + "_iframe";
                        var uniqueUploadProgressID = uniqueID + "_progress";

                        //check for flash version...						
                        var flashVersion = Agility.GetFlashVersion();

                        //build the return url to come back to the blank.htm page

                        returnUrl = returnUrl.substring(0, returnUrl.indexOf("/", returnUrl.indexOf("//") + 2));
                        returnUrl += Agility.ResolveUrl("~/blank.htm");

                        var blankUrl = Agility.ResolveUrl("~/blank.htm");

                        var amazonS3Url = settings.AmazonS3BaseUrl;
                        if (amazonS3Url == undefined || amazonS3Url == null || amazonS3Url == "") {
                            html = jQuery("The Amazon S3 Base Url settings value has not be provided.");
                            html.appendTo(fieldPanel);
                            return;
                        }

                        if (amazonS3Url.lastIndexOf("/") != amazonS3Url.length - 1) amazonS3Url += "/";

                        //yyyy-MM-dd\\THH:mm:ss.fff\\Z 
                        var exDate = new Date();
                        exDate.setDate(exDate.getDate() + 1);
                        var expiration = exDate.getFullYear() + "-" + (exDate.getMonth() + 1) + "-" + exDate.getDate() + "T" + exDate.getHours() + ":" + exDate.getMinutes() + ":" + exDate.getSeconds() + "." + exDate.getTimezoneOffset() + "Z";

                        var baseDirectory = "AgilityUGC/" + GUID;

                        var contentLengthRangeMin = 0;
                        var contentLengthRangeMax = 0;
                        if (fieldType != null && fieldType.MaxLength > 0) {
                            //convert from kb to bytes...
                            contentLengthRangeMax = fieldType.MaxLength * 1024;
                        }

                        var policy = '{ "expiration": "' + expiration + '", ';
                        policy += '"conditions": [  ';
                        policy += '	{"bucket": "' + settings.AmazonS3Bucket + '"}, ';
                        policy += '	["starts-with", "$key", "' + baseDirectory + '"], ';
                        policy += '	{"acl": "public-read"}, ';
                        if (flashVersion <= 8) {
                            policy += '	{"success_action_redirect": "' + returnUrl + '"}, ';
                        } else {
                            policy += '	{"success_action_status": "201"}, ';

                        }
                        policy += '	 ["starts-with", "$Content-Type", ""], [ "starts-with", "$filename", "" ], ';
                        if (contentLengthRangeMax > 0) {
                            policy += ' ["content-length-range", ' + contentLengthRangeMin + ', ' + contentLengthRangeMax + '], ';
                        }

                        policy += '] }';



                        //build the key
                        var awsSecretKey = settings.AmazonS3SecretKey;
                        var awskey = settings.AmazonS3AccessKey;

                        //get the signature from the UGC Server
                        API.GetAmazonS3Signature(policy, function(data) {
                            var policySig = data.ResponseData;


                            var fileTypes = null;
                            //assume that the file extensions are the validation.... eg: .*([\.jpg]|[\.gif]|[\.jpeg]|[\.png])						
                            if (fieldType != null && fieldType.ValidationRegEx != undefined && fieldType.ValidationRegEx != "") {

                                var validExp = fieldType.ValidationRegEx;
                                validExp = validExp.replace(".*([\\", "");
                                validExp = validExp.replace("])", "");

                                while (validExp.indexOf("]|[\\") != -1) {
                                    validExp = validExp.replace("]|[\\", ";");
                                }
                                fileTypes = validExp.replace(/\./g, "*.");

                            }

                            //IF FLASH IS ENABLED....

                            if (Agility.GetFlashVersion() > 8) {
                                html = jQuery("<span id='" + uniqueSwfUploadID + "'></span>");

                                html.appendTo(fieldPanel);

                                var postParams = {
                                    "key": baseDirectory + "/${filename}",
                                    "AWSAccessKeyId": awskey,
                                    "policy": policySig.PolicyBase64,
                                    "acl": "public-read",
                                    "Signature": policySig.Signature,
                                    "success_action_status": "201"
                                };


                                //build the upload swf
                                var swfu = new SWFUpload({
                                    // Backend Settings
                                    upload_url: amazonS3Url,
                                    file_post_name: "file",
                                    post_params: postParams,

                                    // File Upload Settings
                                    file_size_limit: contentLengthRangeMax / 1024,
                                    file_types: fileTypes,
                                    file_types_description: "Valid File Types",
                                    file_upload_limit: "0",    // Zero means unlimited


                                    // Event Handler Settings - these functions as defined in Handlers.js
                                    //  The handlers are not part of SWFUpload but are part of my website and control how
                                    //  my website reacts to the SWFUpload events.
                                    file_queue_error_handler: function(file, errorCode, message) {
                                        jQuery("#" + options.inputID).data("uploading", false);
                                        if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
                                            options.uploadError(file, errorCode, message);
                                        }
                                    },
                                    file_dialog_complete_handler: function(numFilesSelected, numFilesQueued) {
                                        if (numFilesQueued > 0) {
                                            var file = this.getFile();
                                            if (file == null) return;

                                            var filename = file.name;
                                            var mimetype = API.GetMIMEtype(filename);
                                            this.addPostParam("Content-Type", API.GetMIMEtype(filename));
                                            if (options.beforeUpload != undefined && jQuery.isFunction(options.beforeUpload)) {
                                                if (options.beforeUpload(filename, mimetype, file.size, this) == false) {
                                                    return;
                                                }
                                            }

                                            jQuery("#" + options.inputID).data("uploading", true);
                                            this.startUpload();
                                        }

                                    },
                                    upload_progress_handler: function(file, bytesLoaded) {
                                        if (options.uploadProgress != undefined && jQuery.isFunction(options.uploadProgress)) {
                                            options.uploadProgress(file, bytesLoaded);
                                        }
                                    },
                                    upload_success_handler: function(file, serverData) {

                                        //success - set the value of the input and call the event.
                                        var uploadedKey = baseDirectory + "/" + file.name;
                                        jQuery("#" + options.inputID).val(uploadedKey);
                                        jQuery("#" + options.inputID).data("uploading", false);
                                        if (options.uploadComplete != undefined && jQuery.isFunction(options.uploadComplete)) {
                                            options.uploadComplete(uploadedKey, file.size);
                                        }
                                    },
                                    upload_complete_handler: function(file) {
                                        jQuery("#" + options.inputID).data("uploading", false);
                                    },

                                    upload_error_handler: function uploadError(file, errorCode, message) {
                                        jQuery("#" + options.inputID).data("uploading", false);
                                        if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
                                            options.uploadError(file, errorCode, message);
                                        }
                                    },
                                    swfupload_loaded_handler: function() {

                                    },

                                    // Button settings
                                    button_image_url: options.uploadButtonImageUrl,
                                    button_placeholder_id: uniqueSwfUploadID,
                                    button_width: options.uploadButtonImageWidth,
                                    button_height: options.uploadButtonImageHeight,
                                    button_window_mode: SWFUpload.WINDOW_MODE.OPAQUE,
                                    button_action: SWFUpload.BUTTON_ACTION.SELECT_FILE,
                                    button_cursor: SWFUpload.CURSOR.HAND,


                                    // Flash Settings
                                    prevent_swf_caching: false,
                                    flash_url: options.swfUploadUrl, // Relative to this file

                                    // Debug Settings
                                    debug: false
                                });



                            } else {

                                //flash not enabled...

                                //build the html for the form and iframe
                                var formHtml = "<form  enctype=\"multipart/form-data\" id=\"" + uniqueFormID + "\" method=\"post\" action=\"" + amazonS3Url + "\" target=\"" + uniqueIFrameID + "\"  style=\"display:inline\">";
                                formHtml += "<input type=\"hidden\" name=\"key\" />";
                                formHtml += "<input type=\"hidden\" name=\"AWSAccessKeyId\" />";
                                formHtml += "<input type=\"hidden\" name=\"Content-Type\" value=\"\">";
                                formHtml += "<input type=\"hidden\" name=\"success_action_redirect\" value=\"" + returnUrl + "\" />";
                                formHtml += "<input type=\"hidden\" name=\"acl\" value=\"public-read\" />";
                                formHtml += "<input type=\"hidden\" name=\"policy\" value=\"\" />";
                                formHtml += "<input type=\"hidden\" name=\"filename\" value=\"\" />";
                                formHtml += "<input type=\"hidden\" name=\"Signature\" size=\"100\" value=\"\" />";
                                formHtml += "<input id='" + uniqueFileUploadID + "' type=\"file\" name=\"file\" />";
                                formHtml += "</form>"
                                formHtml += "<iframe id=\"" + uniqueIFrameID + "\" name=\"" + uniqueIFrameID + "\" src=\"" + blankUrl + "\" style='position:absolute; height:1px; width: 1px; top:-1px; left: -10000px; overflow:hidden'></iframe>";

                                //build the jQuery object for the form							
                                html = jQuery(formHtml);

                                //add the form to the field panel..							
                                html.appendTo(fieldPanel);

                                //set the field values...							
                                jQuery("input[name='key']", html).val(baseDirectory + "/${filename}");
                                jQuery("input[name='AWSAccessKeyId']", html).val(awskey);
                                jQuery("input[name='policy']", html).val(policySig.PolicyBase64);
                                jQuery("input[name='Signature']", html).val(policySig.Signature);



                                var uploadedFileName = null;

                                //listen to frame load events																			
                                jQuery("#" + uniqueIFrameID).load(function() {
                                    //load event of the iframe...

                                    jQuery("input[name='file']", html).show();

                                    try {
                                        var loc = $(this.contentDocument.location)
                                        var href = loc.attr("href");

                                        var key = Agility.QueryString("key", href);
                                        if (key != null && key != "") {
                                            var url = amazonS3Url + key;

                                            //update the input file...
                                            jQuery("#" + inputID).val(key);
                                            $("#" + inputID).data("uploading", false);

                                            //call the uploadComplete event, pass it the key
                                            if (options.uploadComplete != undefined && jQuery.isFunction(options.uploadComplete)) {
                                                options.uploadComplete(key, -1);
                                            }
                                        }
                                    } catch (Error) {
                                        $("#" + inputID).data("uploading", false);


                                        //call the uploadError event, pass it the Error object
                                        var errorMsg = "An error occurred while uploading."
                                        if (contentLengthRangeMax > 0) {
                                            errorMsg += " Please ensure the file is less than " + (contentLengthRangeMax / 1024) + "kb.";
                                        }

                                        if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) {
                                            options.uploadError("", -1, errorMsg);
                                            throw Error;
                                        } else {
                                            alert(errorMsg);
                                            throw Error;
                                        }
                                    }
                                });

                                //listen to file name changed events...							
                                jQuery("input[name='file']", html).change(function() {
                                    uploadedFileName = $(this).val();

                                    if (uploadedFileName != "") {

                                        //check that filename is of the allowable types...
                                        if (fieldType != null) {
                                            try {
                                                var vldExp = fieldType.ValidationRegEx;
                                                if (vldExp != null && vldExp != "") {
                                                    var rEx = new RegExp(vldExp);
                                                    rEx.ignoreCase = true;
                                                    if (uploadedFileName.search(rEx) == -1) {

                                                        if (options.uploadError != undefined && jQuery.isFunction(uoptions.ploadError)) {
                                                            options.uploadError(uploadedFileName, SWFUpload.QUEUE_ERROR.INVALID_FILETYPE, fieldType.ValidationMessage);
                                                        }

                                                        $(this).val("");
                                                        return;
                                                    }
                                                }
                                            } catch (ex3) {
                                                return;
                                            }
                                        }


                                        //get the mimeType of the file
                                        var mimeType = API.GetMIMEtype(uploadedFileName);

                                        //fire the beforeUpload event
                                        if (options.beforeUpload != undefined && jQuery.isFunction(options.beforeUpload)) {
                                            if (options.beforeUpload(uploadedFileName, mimeType, -1, null) == false) {
                                                try {
                                                    $(this).val("");
                                                } catch (ex2) { }
                                                return;
                                            }
                                        }


                                        //put a marker on the file to show that it has changed...
                                        $("#" + inputID).data("uploading", true);
                                        $("#" + uniqueFormID + " input[name='Content-Type']").val(mimeType);

                                        //submit the form
                                        var f = jQuery("#" + uniqueFormID);
                                        f.submit();

                                        //clear out the input and hide it
                                        try {
                                            $(this).val("");
                                        } catch (ex1) { }
                                        $(this).hide();
                                    }

                                });

                            }

                        });

                    }

                });

            }

        });



        //bind a "live" event to the remove link (this will work for ANY remove link...);		
        if (API._liveAttachmentRemoveHandlerBound != true) {

            API._liveAttachmentRemoveHandlerBound = true;

            jQuery("form a.UploadedFileRemove").live("click", function() {
                if (confirm("Do you wish to delete this file?\n\nYou will not be able to recover this file, and any links to it will be broken")) {

                    //get the associated field ID from the <form> tag
                    var associatedFieldID = jQuery(this).parents("form").data("associatedFieldID");

                    var elem = jQuery(this).parent("span.UploadedFileContainer")
                    elem.html("Deleting file...");

                    var key = jQuery("#" + associatedFieldID).val();
                    API.DeleteFile(key, function(data) {
                        if (data.ResponseType != 0) {
                            elem.html("An error occurred: " + data.Message);
                        } else {
                            elem.html("");
                            jQuery("#" + associatedFieldID).val("");
                        }
                    });
                }
            });
        }
    }

    //global variable used to track whether the  live attachment remove randler event has been bound
    API._liveAttachmentRemoveHandlerBound = false;

    function _buildAPIUrl(methodName, args, query) {
        var url = API.APIUrl;

        //query should be in the form "q1=q1val&s2=s2val

        //ensure the url ends with /
        if (url.lastIndexOf("/") != url.length - 1) url += "/";

        //create the base url for the call
        url += methodName + "/" + API.APIAccessKey + "/" + API.APISeconds + "/" + API.APIRandomNumber + "/" + API.APIHash + "/" + API.APIProfileRecordID;

        //add the arguments for call
        if (args != undefined && $.isArray(args) && args.length > 0) {
            jQuery.each(args, function(index, arg) {
                url += "/" + escape(arg);
            });
        }

        //add the "method" param
        url += "?method=?";

        //add the query strings
        if (query != undefined && query != "") {
            url += "&" + query;
        }

        return url;
    }



    function _submitPostData(url, postData, callback) {

        //build the unique ids
        var uniqueID = Agility.UniqueID("postDataForm");

        var uniqueFormID = uniqueID + "_form";
        var uniqueIFrameID = uniqueID + "_iframe";

        //build the return url to come back to the blank.htm page
        var returnUrl = location.href;
        returnUrl = returnUrl.substring(0, returnUrl.indexOf("/", returnUrl.indexOf("//") + 2));
        returnUrl += Agility.ResolveUrl("~/blank.htm");

        var blankUrl = Agility.ResolveUrl("~/blank.htm");

        //remove the method callback from the url
        url = url.replace("?method=?", "?method=post");

        //build the html for the form and iframe
        var formHtml = "<div id=\"" + uniqueID + "\" style='display:none'><form id=\"" + uniqueFormID + "\" method=\"post\" action=\"" + url + "\" target=\"" + uniqueIFrameID + "\">";
        formHtml += "<input type=\"text\" name=\"postdata\" />";
        formHtml += "<input type=\"text\" name=\"url\" />";
        formHtml += "</form>"
        formHtml += "<iframe id=\"" + uniqueIFrameID + "\" name=\"" + uniqueIFrameID + "\" src=\"" + blankUrl + "\"></iframe>";
        formHtml += "</div>";


        //add the elements to the DOM
        var thisBody = jQuery(document.body);
        jQuery(thisBody).append(formHtml);

        //create the actual DOM elements
        var div = jQuery("#" + uniqueID);
        var form = jQuery("#" + uniqueFormID);
        var iframe = jQuery("#" + uniqueIFrameID);

        $("input[name=postdata]", form).val(postData);
        $("input[name=url]", form).val(returnUrl);

        //capture the load event of the form.
        jQuery(iframe).load(function() {

            var frm = window.frames[uniqueIFrameID];

            var responseType = responseType = API.ResponseType.Error;

            var loc = frm.location;

            if (loc != null) {
                var href = loc.href;

                responseType = parseInt(Agility.QueryString("ResponseType", href));
                if (isNaN(responseType)) responseType = API.ResponseType.Error;
            }


            var data = {
                ResponseType: responseType,
                Message: Agility.QueryString("Message", href),
                ResponseData: Agility.QueryString("ResponseData", href)
            };

            //call the callback
            setTimeout(function() {
                callback(data);
            }, 0);

            //remove the elements...						
            setTimeout(function() {
                div.empty();
            }, 0);

        });

        //submit the form
        form.submit();
    }

    API.GetMIMEtype = function(filename) {
        /// <summary>
        /// Gets the mime-type of a file based on a filename.
        /// </summary>
        /// <param name="filename" type="String">The file name (from a file upload...)</param>


        var fn = new String(filename);
        var fn1 = new String();
        fn1 = fn.match(/[\/\\][^\/\\]*$/);
        if (fn1 != null && fn1.length > 0) fn = fn1 + "";

        fn = fn.toLowerCase();

        if (fn.search(/^.*\.ai$/) >= 0) {
            return ("application/illustrator");
        }
        if (fn.search(/^.*\.bin$/) >= 0) {
            return ("application/octet-stream");
        }
        if (fn.search(/^.*\.pdf$/) >= 0) {
            return ("application/pdf");
        }
        if (fn.search(/^.*\.ps$/) >= 0) {
            return ("application/postscript");
        }
        if (fn.search(/^.*\.rtf$/) >= 0) {
            return ("application/rtf");
        }
        if (fn.search(/^.*\.sit$/) >= 0) {
            return ("application/stuffit");
        }
        if (fn.search(/^.*\.flv$/) >= 0) {
            return ("video/x-flv");
        }
        if (fn.search(/^.*\.mdb$/) >= 0) {
            return ("application/vnd.ms-access");
        }
        if (fn.search(/^.*\.xls$/) >= 0) {
            return ("application/vnd.ms-excel");
        }
        if (fn.search(/^.*\.ppt$/) >= 0) {
            return ("application/vnd.ms-powerpoint");
        }
        if (fn.search(/^.*\.pps$/) >= 0) {
            return ("application/vnd.ms-powerpoint");
        }
        if (fn.search(/^.*\.pot$/) >= 0) {
            return ("application/vnd.ms-powerpoint");
        }
        if (fn.search(/^.*\.xps$/) >= 0) {
            return ("application/vnd.ms-xpsdocument");
        }
        if (fn.search(/^.*\.doc$/) >= 0) {
            return ("application/msword");
        }
        if (fn.search(/^.*\.7z$/) >= 0) {
            return ("application/x-7z-compressed");
        }
        if (fn.search(/^.*\.torrent$/) >= 0) {
            return ("application/x-bittorrent");
        }
        if (fn.search(/^.*\.tar\.gz$/) >= 0) {
            return ("application/x-compressed-tar");
        }
        if (fn.search(/^.*\.tgz$/) >= 0) {
            return ("application/x-compressed-tar");
        }
        if (fn.search(/^.*\.ttf$/) >= 0) {
            return ("application/x-font-ttf");
        }
        if (fn.search(/^.*\.gz$/) >= 0) {
            return ("application/x-gzip");
        }
        if (fn.search(/^.*\.pdf\.gz$/) >= 0) {
            return ("application/x-gzpdf");
        }
        if (fn.search(/^.*\.ps\.gz$/) >= 0) {
            return ("application/x-gzpostscript");
        }
        if (fn.search(/^.*\.jar$/) >= 0) {
            return ("application/x-java-archive");
        }
        if (fn.search(/^.*\.js$/) >= 0) {
            return ("application/javascript");
        }
        if (fn.search(/^.*\.lzh$/) >= 0) {
            return ("application/x-lha");
        }
        if (fn.search(/^.*\.mkv$/) >= 0) {
            return ("video/x-matroska");
        }
        if (fn.search(/^.*\.exe$/) >= 0) {
            return ("application/x-ms-dos-executable");
        }
        if (fn.search(/^.*\.ogg$/) >= 0) {
            return ("application/ogg");
        }
        if (fn.search(/^.*\.ogx$/) >= 0) {
            return ("application/ogg");
        }
        if (fn.search(/^.*\.oga$/) >= 0) {
            return ("audio/ogg");
        }
        if (fn.search(/^.*\.ogv$/) >= 0) {
            return ("video/ogg");
        }
        if (fn.search(/^.*\.ogg$/) >= 0) {
            return ("audio/x-vorbis+ogg");
        }
        if (fn.search(/^.*\.ogg$/) >= 0) {
            return ("audio/x-flac+ogg");
        }
        if (fn.search(/^.*\.ogg$/) >= 0) {
            return ("audio/x-speex+ogg");
        }
        if (fn.search(/^.*\.spx$/) >= 0) {
            return ("audio/x-speex");
        }
        if (fn.search(/^.*\.ogg$/) >= 0) {
            return ("video/x-theora+ogg");
        }
        if (fn.search(/^.*\.ogm$/) >= 0) {
            return ("video/x-ogm+ogg");
        }
        if (fn.search(/^.*\.qtl$/) >= 0) {
            return ("application/x-quicktime-media-link");
        }
        if (fn.search(/^.*\.tar$/) >= 0) {
            return ("application/x-tar");
        }
        if (fn.search(/^.*\.theme$/) >= 0) {
            return ("application/x-theme");
        }
        if (fn.search(/^.*\.der$/) >= 0) {
            return ("application/x-x509-ca-cert");
        }
        if (fn.search(/^.*\.cer$/) >= 0) {
            return ("application/x-x509-ca-cert");
        }
        if (fn.search(/^.*\.crt$/) >= 0) {
            return ("application/x-x509-ca-cert");
        }
        if (fn.search(/^.*\.cert$/) >= 0) {
            return ("application/x-x509-ca-cert");
        }
        if (fn.search(/^.*\.pem$/) >= 0) {
            return ("application/x-x509-ca-cert");
        }
        if (fn.search(/^.*\.xhtml$/) >= 0) {
            return ("application/xhtml+xml");
        }
        if (fn.search(/^.*\.zip$/) >= 0) {
            return ("application/zip");
        }
        if (fn.search(/^.*\.ac3$/) >= 0) {
            return ("audio/ac3");
        }
        if (fn.search(/^.*\.aiff$/) >= 0) {
            return ("audio/x-aiff");
        }
        if (fn.search(/^.*\.aif$/) >= 0) {
            return ("audio/x-aiff");
        }
        if (fn.search(/^.*\.aifc$/) >= 0) {
            return ("audio/x-aiff");
        }
        if (fn.search(/^.*\.flac$/) >= 0) {
            return ("audio/x-flac");
        }
        if (fn.search(/^.*\.mid$/) >= 0) {
            return ("audio/midi");
        }
        if (fn.search(/^.*\.midi$/) >= 0) {
            return ("audio/midi");
        }
        if (fn.search(/^.*\.kar$/) >= 0) {
            return ("audio/midi");
        }
        if (fn.search(/^.*\.m4a$/) >= 0) {
            return ("audio/mp4");
        }
        if (fn.search(/^.*\.aac$/) >= 0) {
            return ("audio/mp4");
        }
        if (fn.search(/^.*\.mp4$/) >= 0) {
            return ("video/mp4");
        }
        if (fn.search(/^.*\.m4v$/) >= 0) {
            return ("video/mp4");
        }
        if (fn.search(/^.*\.m4b$/) >= 0) {
            return ("audio/x-m4b");
        }
        if (fn.search(/^.*\.3gp$/) >= 0) {
            return ("video/3gpp");
        }
        if (fn.search(/^.*\.3gpp$/) >= 0) {
            return ("video/3gpp");
        }
        if (fn.search(/^.*\.amr$/) >= 0) {
            return ("video/3gpp");
        }
        if (fn.search(/^.*\.mp2$/) >= 0) {
            return ("audio/mp2");
        }
        if (fn.search(/^.*\.mp3$/) >= 0) {
            return ("audio/mpeg");
        }
        if (fn.search(/^.*\.mpga$/) >= 0) {
            return ("audio/mpeg");
        }
        if (fn.search(/^.*\.m3u$/) >= 0) {
            return ("audio/x-mpegurl");
        }
        if (fn.search(/^.*\.vlc$/) >= 0) {
            return ("audio/x-mpegurl");
        }
        if (fn.search(/^.*\.asx$/) >= 0) {
            return ("audio/x-ms-asx");
        }
        if (fn.search(/^.*\.wax$/) >= 0) {
            return ("audio/x-ms-asx");
        }
        if (fn.search(/^.*\.wvx$/) >= 0) {
            return ("audio/x-ms-asx");
        }
        if (fn.search(/^.*\.wmx$/) >= 0) {
            return ("audio/x-ms-asx");
        }
        if (fn.search(/^.*\.psf$/) >= 0) {
            return ("audio/x-psf");
        }
        if (fn.search(/^.*\.wma$/) >= 0) {
            return ("audio/x-ms-wma");
        }
        if (fn.search(/^.*\.ra$/) >= 0) {
            return ("audio/vnd.rn-realaudio");
        }
        if (fn.search(/^.*\.rax$/) >= 0) {
            return ("audio/vnd.rn-realaudio");
        }
        if (fn.search(/^.*\.ram$/) >= 0) {
            return ("application/ram");
        }
        if (fn.search(/^.*\.rv$/) >= 0) {
            return ("video/vnd.rn-realvideo");
        }
        if (fn.search(/^.*\.rvx$/) >= 0) {
            return ("video/vnd.rn-realvideo");
        }
        if (fn.search(/^.*\.wav$/) >= 0) {
            return ("audio/x-wav");
        }
        if (fn.search(/^.*\.bmp$/) >= 0) {
            return ("image/bmp");
        }
        if (fn.search(/^.*\.wbmp$/) >= 0) {
            return ("image/vnd.wap.wbmp");
        }
        if (fn.search(/^.*\.gif$/) >= 0) {
            return ("image/gif");
        }
        if (fn.search(/^.*\.jpeg$/) >= 0) {
            return ("image/jpeg");
        }
        if (fn.search(/^.*\.jpg$/) >= 0) {
            return ("image/jpeg");
        }
        if (fn.search(/^.*\.jpe$/) >= 0) {
            return ("image/jpeg");
        }
        if (fn.search(/^.*\.png$/) >= 0) {
            return ("image/png");
        }
        if (fn.search(/^.*\.rle$/) >= 0) {
            return ("image/rle");
        }
        if (fn.search(/^.*\.svg$/) >= 0) {
            return ("image/svg+xml");
        }
        if (fn.search(/^.*\.svgz$/) >= 0) {
            return ("image/svg+xml-compressed");
        }
        if (fn.search(/^.*\.tif$/) >= 0) {
            return ("image/tiff");
        }
        if (fn.search(/^.*\.tiff$/) >= 0) {
            return ("image/tiff");
        }
        if (fn.search(/^.*\.eps$/) >= 0) {
            return ("image/x-eps");
        }
        if (fn.search(/^.*\.ico$/) >= 0) {
            return ("image/x-ico");
        }
        if (fn.search(/^.*\.psd$/) >= 0) {
            return ("image/x-psd");
        }
        if (fn.search(/^.*\.vcs$/) >= 0) {
            return ("text/calendar");
        }
        if (fn.search(/^.*\.ics$/) >= 0) {
            return ("text/calendar");
        }
        if (fn.search(/^.*\.css$/) >= 0) {
            return ("text/css");
        }
        if (fn.search(/^.*\.CSSL$/) >= 0) {
            return ("text/css");
        }
        if (fn.search(/^.*\.rtx$/) >= 0) {
            return ("text/richtext");
        }
        if (fn.search(/^.*\.rss$/) >= 0) {
            return ("application/rss+xml");
        }
        if (fn.search(/^.*\.atom$/) >= 0) {
            return ("application/atom+xml");
        }
        if (fn.search(/^.*\.opml$/) >= 0) {
            return ("text/x-opml+xml");
        }
        if (fn.search(/^.*\.sgml$/) >= 0) {
            return ("text/sgml");
        }
        if (fn.search(/^.*\.sgm$/) >= 0) {
            return ("text/sgml");
        }
        if (fn.search(/^.*\.dtd$/) >= 0) {
            return ("text/x-dtd");
        }
        if (fn.search(/^.*\.html$/) >= 0) {
            return ("text/html");
        }
        if (fn.search(/^.*\.htm$/) >= 0) {
            return ("text/html");
        }
        if (fn.search(/^.*\.log$/) >= 0) {
            return ("text/x-log");
        }
        if (fn.search(/^README*$/) >= 0) {
            return ("text/x-readme");
        }
        if (fn.search(/^.*\.uri$/) >= 0) {
            return ("text/x-uri");
        }
        if (fn.search(/^.*\.url$/) >= 0) {
            return ("text/x-uri");
        }
        if (fn.search(/^.*\.fo$/) >= 0) {
            return ("text/x-xslfo");
        }
        if (fn.search(/^.*\.xslfo$/) >= 0) {
            return ("text/x-xslfo");
        }
        if (fn.search(/^.*\.xml$/) >= 0) {
            return ("application/xml");
        }
        if (fn.search(/^.*\.xsl$/) >= 0) {
            return ("application/xml");
        }
        if (fn.search(/^.*\.xslt$/) >= 0) {
            return ("application/xml");
        }
        if (fn.search(/^.*\.xbl$/) >= 0) {
            return ("application/xml");
        }
        if (fn.search(/^.*\.mpeg$/) >= 0) {
            return ("video/mpeg");
        }
        if (fn.search(/^.*\.mpg$/) >= 0) {
            return ("video/mpeg");
        }
        if (fn.search(/^.*\.mp2$/) >= 0) {
            return ("video/mpeg");
        }
        if (fn.search(/^.*\.mpe$/) >= 0) {
            return ("video/mpeg");
        }
        if (fn.search(/^.*\.vob$/) >= 0) {
            return ("video/mpeg");
        }
        if (fn.search(/^.*\.m2t$/) >= 0) {
            return ("video/mpeg");
        }
        if (fn.search(/^.*\.qt$/) >= 0) {
            return ("video/quicktime");
        }
        if (fn.search(/^.*\.mov$/) >= 0) {
            return ("video/quicktime");
        }
        if (fn.search(/^.*\.moov$/) >= 0) {
            return ("video/quicktime");
        }
        if (fn.search(/^.*\.qtvr$/) >= 0) {
            return ("video/quicktime");
        }
        if (fn.search(/^.*\.qtif$/) >= 0) {
            return ("image/x-quicktime");
        }
        if (fn.search(/^.*\.qif$/) >= 0) {
            return ("image/x-quicktime");
        }
        if (fn.search(/^.*\.viv$/) >= 0) {
            return ("video/vivo");
        }
        if (fn.search(/^.*\.vivo$/) >= 0) {
            return ("video/vivo");
        }
        if (fn.search(/^.*\.anim[1-9j]$/) >= 0) {
            return ("video/x-anim");
        }
        if (fn.search(/^.*\.fli$/) >= 0) {
            return ("video/x-flic");
        }
        if (fn.search(/^.*\.flc$/) >= 0) {
            return ("video/x-flic");
        }
        if (fn.search(/^.*\.hwp$/) >= 0) {
            return ("application/x-hwp");
        }
        if (fn.search(/^.*\.hwt$/) >= 0) {
            return ("application/x-hwt");
        }
        if (fn.search(/^.*\.mng$/) >= 0) {
            return ("video/x-mng");
        }
        if (fn.search(/^.*\.asf$/) >= 0) {
            return ("video/x-ms-asf");
        }
        if (fn.search(/^.*\.nsc$/) >= 0) {
            return ("application/x-netshow-channel");
        }
        if (fn.search(/^.*\.wmv$/) >= 0) {
            return ("video/x-ms-wmv");
        }
        if (fn.search(/^.*\.avi$/) >= 0) {
            return ("video/x-msvideo");
        }
        if (fn.search(/^.*\.divx$/) >= 0) {
            return ("video/x-msvideo");
        }
        return ("binary/octet-stream");
    };


})(Agility.UGC.API, jQuery);
