/*
 *
 * 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.
 *
 */

/* global FileUploadResult */

var argscheck = require('cordova/argscheck');
var FileTransferError = require('./FileTransferError');

function getParentPath (filePath) {
    var pos = filePath.lastIndexOf('/');
    return filePath.substring(0, pos + 1);
}

function getFileName (filePath) {
    var pos = filePath.lastIndexOf('/');
    return filePath.substring(pos + 1);
}

function getUrlCredentials (urlString) {
    var credentialsPattern = /^https?:\/\/(?:(?:(([^:@/]*)(?::([^@/]*))?)?@)?([^:/?#]*)(?::(\d*))?).*$/;
    var credentials = credentialsPattern.exec(urlString);

    return credentials && credentials[1];
}

function getBasicAuthHeader (urlString) {
    var header = null;

    // This is changed due to MS Windows doesn't support credentials in http uris
    // so we detect them by regexp and strip off from result url
    // Proof: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/a327cf3c-f033-4a54-8b7f-03c56ba3203f/windows-foundation-uri-security-problem

    if (window.btoa) {
        var credentials = getUrlCredentials(urlString);
        if (credentials) {
            var authHeader = 'Authorization';
            var authHeaderValue = 'Basic ' + window.btoa(credentials);

            header = {
                name: authHeader,
                value: authHeaderValue
            };
        }
    }

    return header;
}

function checkURL (url) {
    return url.indexOf(' ') === -1;
}

var idCounter = 0;

var transfers = {};

/**
 * FileTransfer uploads a file to a remote server.
 * @constructor
 */
var FileTransfer = function () {
    this._id = ++idCounter;
    this.onprogress = null; // optional callback
};

/**
 * Given an absolute file path, uploads a file on the device to a remote server
 * using a multipart HTTP request.
 * @param filePath {String}           Full path of the file on the device
 * @param server {String}             URL of the server to receive the file
 * @param successCallback (Function}  Callback to be invoked when upload has completed
 * @param errorCallback {Function}    Callback to be invoked upon error
 * @param options {FileUploadOptions} Optional parameters such as file name and mimetype
 * @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false
 */
FileTransfer.prototype.upload = function (filePath, server, successCallback, errorCallback, options) {
    // check for arguments
    argscheck.checkArgs('ssFFO*', 'FileTransfer.upload', arguments);

    // Check if target URL doesn't contain spaces. If contains, it should be escaped first
    // (see https://github.com/apache/cordova-plugin-file-transfer/blob/master/doc/index.md#upload)
    if (!checkURL(server)) {
        if (errorCallback) {
            errorCallback(new FileTransferError(FileTransferError.INVALID_URL_ERR, filePath, server));
        }
        return;
    }

    options = options || {};

    var fileKey = options.fileKey || 'file';
    var fileName = options.fileName || 'image.jpg';
    var mimeType = options.mimeType || 'image/jpeg';
    var params = options.params || {};
    var withCredentials = options.withCredentials || false;
    // var chunkedMode = !!options.chunkedMode; // Not supported
    var headers = options.headers || {};
    var httpMethod = options.httpMethod && options.httpMethod.toUpperCase() === 'PUT' ? 'PUT' : 'POST';

    var basicAuthHeader = getBasicAuthHeader(server);
    if (basicAuthHeader) {
        server = server.replace(getUrlCredentials(server) + '@', '');
        headers[basicAuthHeader.name] = basicAuthHeader.value;
    }

    var that = this;
    var xhr = (transfers[this._id] = new XMLHttpRequest());
    xhr.withCredentials = withCredentials;

    var fail =
        errorCallback &&
        function (code, status, response) {
            if (transfers[this._id]) {
                delete transfers[this._id];
            }
            var error = new FileTransferError(code, filePath, server, status, response);
            if (errorCallback) {
                errorCallback(error);
            }
        };

    window.resolveLocalFileSystemURL(
        filePath,
        function (entry) {
            entry.file(
                function (file) {
                    var reader = new FileReader();
                    reader.onloadend = function () {
                        var blob = new Blob([this.result], { type: mimeType });

                        // Prepare form data to send to server
                        var fd = new FormData();
                        fd.append(fileKey, blob, fileName);
                        for (var prop in params) {
                            if (Object.prototype.hasOwnProperty.call(params, prop)) {
                                fd.append(prop, params[prop]);
                            }
                        }

                        xhr.open(httpMethod, server);

                        // Fill XHR headers
                        for (var header in headers) {
                            if (Object.prototype.hasOwnProperty.call(headers, header)) {
                                xhr.setRequestHeader(header, headers[header]);
                            }
                        }

                        xhr.onload = function () {
                            // 2xx codes are valid
                            if (this.status >= 200 && this.status < 300) {
                                var result = new FileUploadResult();
                                result.bytesSent = blob.size;
                                result.responseCode = this.status;
                                result.response = this.response;
                                delete transfers[that._id];
                                successCallback(result);
                            } else if (this.status === 404) {
                                fail(FileTransferError.INVALID_URL_ERR, this.status, this.response);
                            } else {
                                fail(FileTransferError.CONNECTION_ERR, this.status, this.response);
                            }
                        };

                        xhr.ontimeout = function () {
                            fail(FileTransferError.CONNECTION_ERR, this.status, this.response);
                        };

                        xhr.onerror = function () {
                            fail(FileTransferError.CONNECTION_ERR, this.status, this.response);
                        };

                        xhr.onabort = function () {
                            fail(FileTransferError.ABORT_ERR, this.status, this.response);
                        };

                        xhr.upload.onprogress = function (e) {
                            if (that.onprogress) {
                                that.onprogress(e);
                            }
                        };

                        xhr.send(fd);
                        // Special case when transfer already aborted, but XHR isn't sent.
                        // In this case XHR won't fire an abort event, so we need to check if transfers record
                        // isn't deleted by filetransfer.abort and if so, call XHR's abort method again
                        if (!transfers[that._id]) {
                            xhr.abort();
                        }
                    };
                    reader.readAsArrayBuffer(file);
                },
                function () {
                    fail(FileTransferError.FILE_NOT_FOUND_ERR);
                }
            );
        },
        function () {
            fail(FileTransferError.FILE_NOT_FOUND_ERR);
        }
    );
};

/**
 * Downloads a file form a given URL and saves it to the specified directory.
 * @param source {String}          URL of the server to receive the file
 * @param target {String}         Full path of the file on the device
 * @param successCallback (Function}  Callback to be invoked when upload has completed
 * @param errorCallback {Function}    Callback to be invoked upon error
 * @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false
 * @param options {FileDownloadOptions} Optional parameters such as headers
 */
FileTransfer.prototype.download = function (source, target, successCallback, errorCallback, trustAllHosts, options) {
    argscheck.checkArgs('ssFF*', 'FileTransfer.download', arguments);

    // Check if target URL doesn't contain spaces. If contains, it should be escaped first
    // (see https://github.com/apache/cordova-plugin-file-transfer/blob/master/doc/index.md#download)
    if (!checkURL(source)) {
        if (errorCallback) {
            errorCallback(new FileTransferError(FileTransferError.INVALID_URL_ERR, source, target));
        }
        return;
    }

    options = options || {};

    var headers = options.headers || {};
    var withCredentials = options.withCredentials || false;

    var basicAuthHeader = getBasicAuthHeader(source);
    if (basicAuthHeader) {
        source = source.replace(getUrlCredentials(source) + '@', '');
        headers[basicAuthHeader.name] = basicAuthHeader.value;
    }

    var that = this;
    var xhr = (transfers[this._id] = new XMLHttpRequest());
    xhr.withCredentials = withCredentials;
    var fail =
        errorCallback &&
        function (code, status, response) {
            if (transfers[that._id]) {
                delete transfers[that._id];
            }
            // In XHR GET reqests we're setting response type to Blob
            // but in case of error we need to raise event with plain text response
            if (response instanceof Blob) {
                var reader = new FileReader();
                reader.readAsText(response);
                reader.onloadend = function (e) {
                    var error = new FileTransferError(code, source, target, status, e.target.result);
                    errorCallback(error);
                };
            } else {
                var error = new FileTransferError(code, source, target, status, response);
                errorCallback(error);
            }
        };

    xhr.onload = function (e) {
        var fileNotFound = function () {
            fail(FileTransferError.FILE_NOT_FOUND_ERR);
        };

        var req = e.target;
        // req.status === 0 is special case for local files with file:// URI scheme
        if ((req.status === 200 || req.status === 0) && req.response) {
            window.resolveLocalFileSystemURL(
                getParentPath(target),
                function (dir) {
                    dir.getFile(
                        getFileName(target),
                        { create: true },
                        function writeFile (entry) {
                            entry.createWriter(function (fileWriter) {
                                fileWriter.onwriteend = function (evt) {
                                    if (!evt.target.error) {
                                        entry.filesystemName = entry.filesystem.name;
                                        delete transfers[that._id];
                                        if (successCallback) {
                                            successCallback(entry);
                                        }
                                    } else {
                                        fail(FileTransferError.FILE_NOT_FOUND_ERR);
                                    }
                                };
                                fileWriter.onerror = function () {
                                    fail(FileTransferError.FILE_NOT_FOUND_ERR);
                                };
                                fileWriter.write(req.response);
                            }, fileNotFound);
                        },
                        fileNotFound
                    );
                },
                fileNotFound
            );
        } else if (req.status === 404) {
            fail(FileTransferError.INVALID_URL_ERR, req.status, req.response);
        } else {
            fail(FileTransferError.CONNECTION_ERR, req.status, req.response);
        }
    };

    xhr.onprogress = function (e) {
        if (that.onprogress) {
            that.onprogress(e);
        }
    };

    xhr.onerror = function () {
        fail(FileTransferError.CONNECTION_ERR, this.status, this.response);
    };

    xhr.onabort = function () {
        fail(FileTransferError.ABORT_ERR, this.status, this.response);
    };

    xhr.open('GET', source, true);

    for (var header in headers) {
        if (Object.prototype.hasOwnProperty.call(headers, header)) {
            xhr.setRequestHeader(header, headers[header]);
        }
    }

    xhr.responseType = 'blob';

    xhr.send();
};

/**
 * Aborts the ongoing file transfer on this object. The original error
 * callback for the file transfer will be called if necessary.
 */
FileTransfer.prototype.abort = function () {
    if (this instanceof FileTransfer) {
        if (transfers[this._id]) {
            transfers[this._id].abort();
            delete transfers[this._id];
        }
    }
};

module.exports = FileTransfer;
