/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

/*jshint -W030 */
/*global Windows, WinJS*/
/*global module, require*/

var FTErr = require('./FileTransferError'),
    ProgressEvent = require('org.apache.cordova.file.ProgressEvent'),
    FileUploadResult = require('org.apache.cordova.file.FileUploadResult'),
    FileProxy = require('org.apache.cordova.file.FileProxy'),
    FileEntry = require('org.apache.cordova.file.FileEntry');

var appData = Windows.Storage.ApplicationData.current;


// Some private helper functions, hidden by the module
function cordovaPathToNative(path) {

    var cleanPath = String(path);
    // turn / into \\
    cleanPath = cleanPath.replace(/\//g, '\\');
    // turn  \\ into \
    cleanPath = cleanPath.replace(/\\\\/g, '\\');
    // strip end \\ characters
    cleanPath = cleanPath.replace(/\\+$/g, '');
    return cleanPath;
}

function nativePathToCordova(path) {
    return String(path).replace(/\\/g, '/');
}

var fileTransferOps = [];

function FileTransferOperation(state, promise) {
    this.state = state;
    this.promise = promise;
}

FileTransferOperation.PENDING = 0;
FileTransferOperation.DONE = 1;
FileTransferOperation.CANCELLED = 2;


module.exports = {

/*
exec(win, fail, 'FileTransfer', 'upload', 
[filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode, headers, this._id, httpMethod]);
*/
    upload:function(successCallback, errorCallback, options) {
        var filePath = options[0];
        var server = options[1];
        var fileKey = options[2] || 'source';
        var fileName = options[3];
        var mimeType = options[4];
        var params = options[5];
        // var trustAllHosts = options[6]; // todo
        // var chunkedMode = options[7]; // todo 
        var headers = options[8] || {};
        var uploadId = options[9];

        if (!filePath || (typeof filePath !== 'string')) {
            errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR,null,server));
            return;
        }

        if (filePath.substr(0, 8) === "file:///") {
            filePath = appData.localFolder.path + filePath.substr(8).split("/").join("\\");
        } else if (filePath.indexOf('ms-appdata:///') === 0) {
            // Handle 'ms-appdata' scheme
            filePath = filePath.replace('ms-appdata:///local', appData.localFolder.path)
                               .replace('ms-appdata:///temp', appData.temporaryFolder.path);
        }
        // normalize path separators
        filePath = cordovaPathToNative(filePath);

        // Create internal download operation object
        fileTransferOps[uploadId] = new FileTransferOperation(FileTransferOperation.PENDING, null);

        Windows.Storage.StorageFile.getFileFromPathAsync(filePath)
        .then(function (storageFile) {

            if(!fileName) {
                fileName = storageFile.name;
            }
            if(!mimeType) {
                // use the actual content type of the file, probably this should be the default way.
                // other platforms probably can't look this up.
                mimeType = storageFile.contentType;
            }

            // check if download isn't already cancelled
            var uploadOp = fileTransferOps[uploadId];
            if (uploadOp && uploadOp.state === FileTransferOperation.CANCELLED) {
                // Here we should call errorCB with ABORT_ERR error
                errorCallback(new FTErr(FTErr.ABORT_ERR, nativePathToCordova(filePath), server));
                return;
            }

            // setting request headers for uploader
            var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
            for (var header in headers) {
                if (headers.hasOwnProperty(header)) {
                    uploader.setRequestHeader(header, headers[header]);
                }
            }

            // adding params supplied to request payload
            var transferParts = [];
            for (var key in params) {
                if (params.hasOwnProperty(key)) {
                    var contentPart = new Windows.Networking.BackgroundTransfer.BackgroundTransferContentPart();
                    contentPart.setHeader("Content-Disposition", "form-data; name=\"" + key + "\"");
                    contentPart.setText(params[key]);
                    transferParts.push(contentPart);
                }
            }

            // Adding file to upload to request payload
            var fileToUploadPart = new Windows.Networking.BackgroundTransfer.BackgroundTransferContentPart(fileKey, fileName);
            fileToUploadPart.setFile(storageFile);
            transferParts.push(fileToUploadPart);

            // create download object. This will throw an exception if URL is malformed
            var uri = new Windows.Foundation.Uri(server);
            try {
                uploader.createUploadAsync(uri, transferParts).then(
                    function (upload) {
                        // update internal TransferOperation object with newly created promise
                        var uploadOperation = upload.startAsync();
                        fileTransferOps[uploadId].promise = uploadOperation;

                        uploadOperation.then(
                            function (result) {
                                // Update TransferOperation object with new state, delete promise property
                                // since it is not actual anymore
                                var currentUploadOp = fileTransferOps[uploadId];
                                if (currentUploadOp) {
                                    currentUploadOp.state = FileTransferOperation.DONE;
                                    currentUploadOp.promise = null;
                                }

                                var response = result.getResponseInformation();
                                // creating a data reader, attached to response stream to get server's response
                                var reader = new Windows.Storage.Streams.DataReader(result.getResultStreamAt(0));
                                reader.loadAsync(result.progress.bytesReceived).then(function(size) {
                                    var responseText = reader.readString(size);
                                    var ftResult = new FileUploadResult(size, response.statusCode, responseText);
                                    successCallback(ftResult);
                                    reader.close();
                                });
                            },
                            function (error) {
                                var source = nativePathToCordova(filePath);

                                // Handle download error here.
                                // Wrap this routines into promise due to some async methods
                                var getTransferError = new WinJS.Promise(function(resolve) {
                                    if (error.message === 'Canceled') {
                                        // If download was cancelled, message property will be specified
                                        resolve(new FTErr(FTErr.ABORT_ERR, source, server, null, null, error));
                                    } else {
                                        // in the other way, try to get response property
                                        var response = upload.getResponseInformation();
                                        if (!response) {
                                            resolve(new FTErr(FTErr.CONNECTION_ERR, source, server));
                                        } else {
                                            var reader = new Windows.Storage.Streams.DataReader(upload.getResultStreamAt(0));
                                            reader.loadAsync(upload.progress.bytesReceived).then(function (size) {
                                                var responseText = reader.readString(size);
                                                resolve(new FTErr(FTErr.FILE_NOT_FOUND_ERR, source, server, response.statusCode, responseText, error));
                                                reader.close();
                                            });
                                        }
                                    }
                                });

                                // Update TransferOperation object with new state, delete promise property
                                // since it is not actual anymore
                                var currentUploadOp = fileTransferOps[uploadId];
                                if (currentUploadOp) {
                                    currentUploadOp.state = FileTransferOperation.CANCELLED;
                                    currentUploadOp.promise = null;
                                }

                                // Cleanup, remove incompleted file
                                getTransferError.then(function(transferError) {
                                    storageFile.deleteAsync().then(function() {
                                        errorCallback(transferError);
                                    });
                                });
                            },
                            function (evt) {
                                var progressEvent = new ProgressEvent('progress', {
                                    loaded: evt.progress.bytesSent,
                                    total: evt.progress.totalBytesToSend,
                                    target: evt.resultFile
                                });
                                progressEvent.lengthComputable = true;
                                successCallback(progressEvent, { keepCallback: true });
                            }
                        );
                    },
                    function (err) {
                        var errorObj = new FTErr(FTErr.INVALID_URL_ERR);
                        errorObj.exception = err;
                        errorCallback(errorObj);
                    }
                );
            } catch (e) {
                errorCallback(new FTErr(FTErr.INVALID_URL_ERR));
            }
        }, function(err) {
            errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR, server, server, null, null, err));
        });
    },

    // [source, target, trustAllHosts, id, headers]
    download:function(successCallback, errorCallback, options) {
        var source = options[0];
        var target = options[1];
        var downloadId = options[3];
        var headers = options[4] || {};

        if (!target) {
            errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR));
            return;
        }
        if (target.substr(0, 8) === "file:///") {
            target = appData.localFolder.path + target.substr(8).split("/").join("\\");
        } else if (target.indexOf('ms-appdata:///') === 0) {
            // Handle 'ms-appdata' scheme
            target = target.replace('ms-appdata:///local', appData.localFolder.path)
                           .replace('ms-appdata:///temp', appData.temporaryFolder.path);
        }
        target = cordovaPathToNative(target);

        var path = target.substr(0, target.lastIndexOf("\\"));
        var fileName = target.substr(target.lastIndexOf("\\") + 1);
        if (path === null || fileName === null) {
            errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR));
            return;
        }

        var download = null;

        // Create internal download operation object
        fileTransferOps[downloadId] = new FileTransferOperation(FileTransferOperation.PENDING, null);

        var downloadCallback = function(storageFolder) {
            storageFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.generateUniqueName).then(function(storageFile) {

                // check if download isn't already cancelled
                var downloadOp = fileTransferOps[downloadId];
                if (downloadOp && downloadOp.state === FileTransferOperation.CANCELLED) {
                    // Here we should call errorCB with ABORT_ERR error
                    errorCallback(new FTErr(FTErr.ABORT_ERR, source, target));
                    return;
                }

                // if download isn't cancelled, contunue with creating and preparing download operation
                var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
                for (var header in headers) {
                    if (headers.hasOwnProperty(header)) {
                        downloader.setRequestHeader(header, headers[header]);
                    }
                }

                // create download object. This will throw an exception if URL is malformed
                try {
                    var uri = Windows.Foundation.Uri(source);
                    download = downloader.createDownload(uri, storageFile);
                } catch (e) {
                    // so we handle this and call errorCallback
                    errorCallback(new FTErr(FTErr.INVALID_URL_ERR));
                    return;
                }

                var downloadOperation = download.startAsync();
                // update internal TransferOperation object with newly created promise
                fileTransferOps[downloadId].promise = downloadOperation;

                downloadOperation.then(function () {

                    // Update TransferOperation object with new state, delete promise property
                    // since it is not actual anymore
                    var currentDownloadOp = fileTransferOps[downloadId];
                    if (currentDownloadOp) {
                        currentDownloadOp.state = FileTransferOperation.DONE;
                        currentDownloadOp.promise = null;
                    }

                    var nativeURI = storageFile.path.replace(appData.localFolder.path, 'ms-appdata:///local')
                        .replace(appData.temporaryFolder.path, 'ms-appdata:///temp')
                        .replace('\\', '/');

                    // Passing null as error callback here because downloaded file should exist in any case
                    // otherwise the error callback will be hit during file creation in another place
                    FileProxy.resolveLocalFileSystemURI(successCallback, null, [nativeURI]);
                }, function(error) {

                    var getTransferError = new WinJS.Promise(function (resolve) {
                        // Handle download error here. If download was cancelled,
                        // message property will be specified
                        if (error.message === 'Canceled') {
                            resolve(new FTErr(FTErr.ABORT_ERR, source, target, null, null, error));
                        } else {
                            // in the other way, try to get response property
                            var response = download.getResponseInformation();
                            if (!response) {
                                resolve(new FTErr(FTErr.CONNECTION_ERR, source, target));
                            } else {
                                var reader = new Windows.Storage.Streams.DataReader(download.getResultStreamAt(0));
                                reader.loadAsync(download.progress.bytesReceived).then(function (bytesLoaded) {
                                    var payload = reader.readString(bytesLoaded);
                                    resolve(new FTErr(FTErr.FILE_NOT_FOUND_ERR, source, target, response.statusCode, payload, error));
                                });
                            }
                        }
                    });
                    getTransferError.then(function (fileTransferError) {

                        // Update TransferOperation object with new state, delete promise property
                        // since it is not actual anymore
                        var currentDownloadOp = fileTransferOps[downloadId];
                        if (currentDownloadOp) {
                            currentDownloadOp.state = FileTransferOperation.CANCELLED;
                            currentDownloadOp.promise = null;
                        }

                        // Cleanup, remove incompleted file
                        storageFile.deleteAsync().then(function() {
                            errorCallback(fileTransferError);
                        });
                    });

                }, function(evt) {

                    var progressEvent = new ProgressEvent('progress', {
                        loaded: evt.progress.bytesReceived,
                        total: evt.progress.totalBytesToReceive,
                        target: evt.resultFile
                    });
                    progressEvent.lengthComputable = true;

                    successCallback(progressEvent, { keepCallback: true });
                });
            }, function(error) {
                errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR, source, target, null, null, error));
            });
        };
        
        var fileNotFoundErrorCallback = function(error) {
            errorCallback(new FTErr(FTErr.FILE_NOT_FOUND_ERR, source, target, null, null, error));
        };

        Windows.Storage.StorageFolder.getFolderFromPathAsync(path).then(downloadCallback, function (error) {
            // Handle non-existent directory
            if (error.number === -2147024894) {
                var parent = path.substr(0, path.lastIndexOf('\\')),
                    folderNameToCreate = path.substr(path.lastIndexOf('\\') + 1);

                Windows.Storage.StorageFolder.getFolderFromPathAsync(parent).then(function(parentFolder) {
                    parentFolder.createFolderAsync(folderNameToCreate).then(downloadCallback, fileNotFoundErrorCallback);
                }, fileNotFoundErrorCallback);
            } else {
                fileNotFoundErrorCallback();
            }
        });
    },

    abort: function (successCallback, error, options) {
        var fileTransferOpId = options[0];

        // Try to find transferOperation with id specified, and cancel its' promise
        var currentOp = fileTransferOps[fileTransferOpId];
        if (currentOp) {
            currentOp.state = FileTransferOperation.CANCELLED;
            currentOp.promise && currentOp.promise.cancel();
        }
    }

};

require("cordova/exec/proxy").add("FileTransfer",module.exports);
