var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Component, ElementRef, Input, Output, ViewChild } from "@angular/core";
import { ValueField } from "../value-field";
import { HttpClient, HttpEventType, HttpParams, HttpRequest, HttpResponse } from "@angular/common/http";
var FileUploadComponent = /** @class */ (function () {
    function FileUploadComponent(http) {
        this.http = http;
        this.dragActive = false;
    }
    FileUploadComponent.prototype.onDropFile = function (event) {
        this.dragActive = false;
        event.preventDefault();
        this.uploadFile(event.dataTransfer.files);
    };
    FileUploadComponent.prototype.onDragOverFile = function (event) {
        this.dragActive = true;
        event.stopPropagation();
        event.preventDefault();
    };
    FileUploadComponent.prototype.onDragLeave = function () {
        this.dragActive = false;
    };
    FileUploadComponent.prototype.selectFile = function (event) {
        this.uploadFile(event.target.files);
    };
    FileUploadComponent.prototype.uploadFile = function (files) {
        var _this = this;
        if (files.length === 0) {
            console.log("No file selected!");
            return;
        }
        // check if file limit is exceeded
        if (!this.field.checkFileLimit(files.length)) {
            this.resetFileUploadElement();
            return;
        }
        // check file sizes
        if (!this.field.checkFileSize(files)) {
            this.resetFileUploadElement();
            return;
        }
        // upload submitted files
        Array.from(files).forEach(function (file) {
            _this.doUpload(_this.field.getForm().getApp().getBackendUrl() + _this.field.url, file)
                .subscribe(function (event) {
                if (event.type === HttpEventType.UploadProgress) {
                    var percentDone = Math.round(100 * event.loaded / event.total);
                    var uploadFile = _this.field.findCurrentUpload(file.name);
                    if (uploadFile == null) {
                        uploadFile = _this.addNewPathFile(file);
                    }
                    uploadFile.uploadProgress = percentDone;
                }
                else if (event instanceof HttpResponse) {
                    var uploadFile = _this.field.findCurrentUpload(file.name);
                    if (uploadFile == null) {
                        uploadFile = _this.addNewPathFile(file);
                    }
                    var key = new PathFileKey(event.body["key"]["key"], event.body["key"]["name"]);
                    uploadFile.key = key;
                    uploadFile.uploadFinished = true;
                    uploadFile.uploadSuccessful = true;
                    _this.field.updateRequiredStatus();
                }
            }, function (err) {
                console.log("Upload Error:", err);
                var uploadFile = _this.field.findCurrentUpload(file.name);
                if (uploadFile) {
                    uploadFile.sizeString = "Error";
                    uploadFile.uploadFinished = true;
                }
                else {
                    console.log("error: file should exist (" + file.name + ")");
                }
                _this.resetFileUploadElement();
            }, function () {
                _this.resetFileUploadElement();
            });
        });
    };
    FileUploadComponent.prototype.addNewPathFile = function (file) {
        var uploadFile = new PathFile();
        uploadFile.name = file.name;
        uploadFile.size = file.size;
        uploadFile.sizeString = this.field.getReadableFileSizeString(file.size);
        uploadFile.active = true;
        this.field.value.push(uploadFile);
        this.field.sortValues();
        return uploadFile;
    };
    FileUploadComponent.prototype.resetFileUploadElement = function () {
        var count = this.field.value.reduce(function (acc, cur) { return !cur.uploadFinished ? ++acc : acc; }, 0);
        if (count === 0) {
            this.fileInputReference.nativeElement.value = "";
        }
    };
    FileUploadComponent.prototype.doUpload = function (url, file) {
        var formData = new FormData();
        formData.append("upload", file);
        var params = new HttpParams();
        var options = {
            params: params,
            reportProgress: true,
        };
        var req = new HttpRequest("POST", url, formData, options);
        return this.http.request(req); // <any> fixes TS2719
    };
    __decorate([
        Input("field"),
        Output("field"),
        __metadata("design:type", FileUploadField)
    ], FileUploadComponent.prototype, "field", void 0);
    __decorate([
        ViewChild("fileInput", { static: true }),
        __metadata("design:type", ElementRef)
    ], FileUploadComponent.prototype, "fileInputReference", void 0);
    FileUploadComponent = __decorate([
        Component({
            selector: "path-file-upload",
            templateUrl: "file-upload.component.html"
        }),
        __metadata("design:paramtypes", [HttpClient])
    ], FileUploadComponent);
    return FileUploadComponent;
}());
export { FileUploadComponent };
var FileUploadField = /** @class */ (function (_super) {
    __extends(FileUploadField, _super);
    function FileUploadField(form, translationService) {
        var _this = _super.call(this, form, translationService) || this;
        _this._multiple = true;
        _this._acceptedFileTypes = [];
        _this._fileLimit = 0;
        _this._singleFileSizeLimit = 0;
        _this._allFilesSizeLimit = 0;
        _this.value = [];
        _this._acceptedFileTypes.push("*.*");
        _this.updateRequiredStatus();
        return _this;
    }
    FileUploadField.prototype.setValue = function (value) {
        var files = [];
        for (var _i = 0, value_1 = value; _i < value_1.length; _i++) {
            var item = value_1[_i];
            var file = Object.assign(new PathFile(), item);
            file.key = Object.assign(new PathFileKey(null, null), item.key);
            files.push(file);
        }
        this.sortValues();
        _super.prototype.setValue.call(this, files);
        this.updateRequiredStatus();
    };
    FileUploadField.prototype.sortValues = function () {
        this.value.sort(function (a, b) { return a.name.localeCompare(b.name); });
    };
    Object.defineProperty(FileUploadField.prototype, "url", {
        get: function () {
            return this._url;
        },
        set: function (value) {
            this._url = value;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(FileUploadField.prototype, "multiple", {
        get: function () {
            return this._multiple;
        },
        set: function (value) {
            this._multiple = value;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(FileUploadField.prototype, "acceptedFileTypes", {
        get: function () {
            return this._acceptedFileTypes;
        },
        set: function (value) {
            this._acceptedFileTypes = value;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(FileUploadField.prototype, "fileUploadRequired", {
        get: function () {
            return this._fileUploadRequired;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(FileUploadField.prototype, "fileLimit", {
        get: function () {
            return this._fileLimit;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(FileUploadField.prototype, "singleFileSizeLimit", {
        get: function () {
            return this._singleFileSizeLimit;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(FileUploadField.prototype, "allFilesSizeLimit", {
        get: function () {
            return this._allFilesSizeLimit;
        },
        enumerable: false,
        configurable: true
    });
    FileUploadField.prototype.remove = function (index, key) {
        if (key) {
            var file = this.find(key);
            if (file) {
                file.active = false;
            }
            this.updateRequiredStatus();
        }
        else {
            this.value.splice(index, 1);
        }
    };
    FileUploadField.prototype.find = function (key) {
        for (var _i = 0, _a = this.value; _i < _a.length; _i++) {
            var file = _a[_i];
            if (file.key.equals(key)) {
                return file;
            }
        }
        return null;
    };
    FileUploadField.prototype.findCurrentUpload = function (name) {
        for (var _i = 0, _a = this.value; _i < _a.length; _i++) {
            var file = _a[_i];
            if (file.name === name && !file.uploadFinished) {
                return file;
            }
        }
        return null;
    };
    FileUploadField.prototype.updateRequiredStatus = function () {
        var uploadInProgressCount = 0;
        var uploadSuccessfulCount = 0;
        this.value.forEach(function (file) {
            if (file.active && !file.uploadFinished) {
                uploadInProgressCount++;
            }
            if (file.active && file.uploadSuccessful) {
                uploadSuccessfulCount++;
            }
        });
        var newStatus = false;
        if (uploadInProgressCount > 0) {
            // always required if upload in progress
            newStatus = true;
        }
        else if (this.required && uploadSuccessfulCount <= 0) {
            newStatus = true;
        }
        this._fileUploadRequired = newStatus;
    };
    FileUploadField.prototype.checkFileLimit = function (newFilesLength) {
        var activeFileCount = 0;
        this.value.forEach(function (file) {
            if (file.active) {
                activeFileCount++;
            }
        });
        if (this.fileLimit > 0 && ((activeFileCount + newFilesLength) > this.fileLimit)) {
            var message = this.translationService.getText("FileLimitMessage", String(this.fileLimit));
            this.getForm().getApp().yesNo(message, function () { }, function () { });
            return false;
        }
        return true;
    };
    FileUploadField.prototype.checkFileSize = function (files) {
        if (this._singleFileSizeLimit || this._allFilesSizeLimit) {
            // check single file limit
            var sizeSum_1 = 0;
            var fileArray = Array.from(files);
            for (var _i = 0, fileArray_1 = fileArray; _i < fileArray_1.length; _i++) {
                var file = fileArray_1[_i];
                sizeSum_1 += file.size;
                if (this._singleFileSizeLimit > 0 && file.size > this._singleFileSizeLimit) {
                    var message = this.translationService.getText("FileSingleSizeMessage", this.getReadableFileSizeString(this._singleFileSizeLimit));
                    this.getForm().getApp().yesNo(message, function () { }, function () { });
                    return false;
                }
            }
            // check sum limit
            if (this._allFilesSizeLimit > 0) {
                this.value.forEach(function (file) {
                    if (file.active) {
                        sizeSum_1 += file.size;
                    }
                });
                if (this._allFilesSizeLimit > 0 && sizeSum_1 > this._allFilesSizeLimit) {
                    var message = this.translationService.getText("FileAllSizeMessage", this.getReadableFileSizeString(this._allFilesSizeLimit));
                    this.getForm().getApp().yesNo(message, function () { }, function () { });
                    return false;
                }
            }
        }
        return true;
    };
    FileUploadField.prototype.getReadableFileSizeString = function (byteSize) {
        var i = -1;
        var byteUnits = [" kB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB"];
        do {
            byteSize = byteSize / 1024;
            i++;
        } while (byteSize > 1024);
        return Math.max(byteSize, 0.1).toFixed(1) + byteUnits[i];
    };
    FileUploadField.prototype.download = function (key) {
        window.location.assign(this.getForm().getApp().getBackendUrl() + this.url + "/" + key.key);
    };
    FileUploadField.prototype.fromJson = function (modelFormField) {
        _super.prototype.fromJson.call(this, modelFormField);
        this.type = "fileUpload";
        if (modelFormField["url"]) {
            this.url = modelFormField["url"];
        }
        if (modelFormField["multiple"] != null) {
            this.multiple = modelFormField["multiple"];
        }
        if (modelFormField["acceptedFileTypes"]) {
            this.acceptedFileTypes = modelFormField["acceptedFileTypes"];
        }
        if (modelFormField["fileLimit"]) {
            this._fileLimit = modelFormField["fileLimit"];
        }
        if (modelFormField["singleFileSizeLimit"]) {
            this._singleFileSizeLimit = modelFormField["singleFileSizeLimit"];
        }
        if (modelFormField["allFilesSizeLimit"]) {
            this._allFilesSizeLimit = modelFormField["allFilesSizeLimit"];
        }
        this.updateRequiredStatus();
    };
    return FileUploadField;
}(ValueField));
export { FileUploadField };
var PathFile = /** @class */ (function () {
    function PathFile() {
        this.uploadFinished = false;
        this.uploadSuccessful = false;
        this.uploadProgress = 0;
        this.size = 0;
    }
    return PathFile;
}());
export { PathFile };
// TODO unify with list key
// tslint:disable:max-classes-per-file
var PathFileKey = /** @class */ (function () {
    function PathFileKey(key, name) {
        this.key = key;
        this.name = name;
    }
    PathFileKey.prototype.equals = function (otherKey) {
        if (otherKey != null &&
            otherKey.name &&
            otherKey.key &&
            this.name &&
            this.key &&
            otherKey.name === this.name &&
            otherKey.key === this.key) {
            return true;
        }
        return false;
    };
    return PathFileKey;
}());
export { PathFileKey };
//# sourceMappingURL=file-upload.component.js.map