import * as i1 from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';
import * as i0 from '@angular/core';
import { EventEmitter, ViewChild, Output, Input, Optional, Component, NgModule } from '@angular/core';
import * as i6 from '@angular/forms';
import { Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
import * as i3 from '@angular/platform-browser';
import * as i2 from '@aztrix/environment';
import * as i4 from '@aztrix/sdk';
import { ReplaySubject } from 'rxjs';
import { mergeMap, startWith, map, shareReplay, first } from 'rxjs/operators';
import * as i5 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i7 from '@angular/material/form-field';
import { MatFormFieldModule } from '@angular/material/form-field';
import * as i8 from '@angular/material/input';
import { MatInputModule } from '@angular/material/input';
import * as i9 from '@angular/material/button';
import { MatButtonModule } from '@angular/material/button';
import * as i10 from '@aztrix/icons';
import { IconsModule } from '@aztrix/icons';
import * as i11 from '@aztrix/components/button';
import { ButtonModule } from '@aztrix/components/button';
import * as i12 from '@aztrix/components/image-preview-button';
import { ImagePreviewButtonModule } from '@aztrix/components/image-preview-button';
import * as i13 from '@aztrix/translate';
import { TranslatePipe } from '@aztrix/translate';

const MAX_FILE_SIZE = 10000000;
const FILE_TYPES = ['pdf', 'doc', 'docx', 'xls', 'pages', 'numbers'];
class FileValueEditComponent {
    constructor(_http, _urlTransformer, _sanitizer, _changeDetector, _configuration) {
        this._http = _http;
        this._urlTransformer = _urlTransformer;
        this._sanitizer = _sanitizer;
        this._changeDetector = _changeDetector;
        this._configuration = _configuration;
        this.acceptTypes = FILE_TYPES;
        this.maxFileSize = MAX_FILE_SIZE;
        this.required = false;
        this.preview = false;
        this.demo = false;
        this.readonly = false;
        this.subscriptSizing = 'dynamic';
        this.clearedValue = new EventEmitter();
        this.uploadedFile = new EventEmitter();
        this.uploading = false;
        this.error = false;
        this.fileControl$ = new ReplaySubject(1);
        this.key$ = this.fileControl$.pipe(mergeMap((fileControl) => fileControl.valueChanges.pipe(startWith(fileControl.value))), map((value) => {
            if (value) {
                return value.id;
            }
            else {
                return null;
            }
        }), shareReplay(1));
        this.source$ = this.key$.pipe(map((key) => this.previewUrl + key));
    }
    ngOnInit() {
        if (!this.fileControl) {
            throw Error('FileValueEditComponent should have a predefined FormControl as input property');
        }
    }
    ngOnChanges(changes) {
        if (changes.maxFileSize) {
            if (this.maxFileSize > MAX_FILE_SIZE) {
                console.error(`input maxFileSize may not be larger than the backend limit (${MAX_FILE_SIZE})`);
                this.maxFileSize = MAX_FILE_SIZE;
            }
            if (!this.maxFileSize || this.maxFileSize <= 0) {
                this.maxFileSize = MAX_FILE_SIZE;
            }
        }
        if ((changes.nameControl || changes.acceptTypes || changes.maxFileSize) && this.nameControl) {
            if (!this.acceptTypes.length) {
                this.acceptTypes = FILE_TYPES;
            }
            this.nameControl.setValidators([
                () => (this.error ? { 'file-upload-failed': {} } : null),
                this._fileTypeValidator(this.acceptTypes, this.types),
                this._maxFileSizeExceeded(this.maxFileSize),
            ]);
            if (this.required) {
                this.nameControl.addValidators([Validators.required]);
            }
        }
        if (changes.fileControl && this.fileControl) {
            this.fileControl$.next(this.fileControl);
        }
    }
    ngOnDestroy() {
        if (this.demoUrlObject) {
            URL.revokeObjectURL(this.demoUrlObject);
        }
    }
    selectFile() {
        if (!this.uploading) {
            this.fileSelect.nativeElement.click();
        }
    }
    fileSelected(event) {
        const file = (event.target.files || [])[0];
        if (!file) {
            return;
        }
        this.fileControl.setValue({ file });
        this.nameControl?.setValue(file.name);
        this.error = false;
        this._changeDetector.detectChanges();
        this.nameControl?.markAsTouched();
        this.nameControl?.updateValueAndValidity();
        if (this.fileControl.invalid || this.nameControl?.invalid) {
            return;
        }
        const formData = new FormData();
        formData.append('file', file);
        this.uploading = true;
        this.fileControl.updateValueAndValidity();
        if (this.demo) {
            this.fileControl.setValue({ id: '0', file });
            this.uploading = false;
            if (this.demoUrlObject) {
                URL.revokeObjectURL(this.demoUrlObject);
            }
            this.demoUrlObject = URL.createObjectURL(file);
        }
        else {
            const transformedUrl = this._urlTransformer.transformUrl(this.uploadLink);
            let headers = new HttpHeaders();
            if (this._configuration.credentials) {
                const authToken = this._configuration.lookupCredential('AuthToken');
                if (authToken) {
                    headers = headers.set('AuthToken', authToken);
                }
            }
            this._http
                .post(transformedUrl, formData, {
                observe: 'body',
                responseType: 'text',
                headers,
            })
                .pipe(first())
                .subscribe({
                next: (id) => {
                    this.fileControl.setValue({ id, file });
                },
                error: () => {
                    this.uploading = false;
                    this.error = true;
                    this._changeDetector.detectChanges();
                    this.fileControl.setValue({});
                    this.fileControl.updateValueAndValidity();
                    this.nameControl?.setValue(undefined);
                    this.fileSelect.nativeElement.value = '';
                    this.nameControl?.updateValueAndValidity();
                },
                complete: () => {
                    this.uploading = false;
                    this.uploadedFile.next(true);
                    this.nameControl?.updateValueAndValidity();
                },
            });
        }
    }
    clearValue(event) {
        event.preventDefault();
        this.fileControl.setValue(undefined);
        this.nameControl?.setValue(undefined);
        this.fileSelect.nativeElement.value = '';
        if (!this.nameControl?.value && this.required) {
            this.nameControl?.setErrors({ required: true });
        }
        else {
            this.nameControl?.setErrors(null);
        }
        this.clearedValue.next(true);
    }
    get fileSizeError() {
        return this.nameControl?.getError('max-file-size-exceeded');
    }
    get fileTypeError() {
        return this.nameControl?.getError('incorrect-file-type');
    }
    get fileUploadFailed() {
        return this.nameControl?.getError('file-upload-failed');
    }
    get requiredError() {
        return this.nameControl?.getError('required');
    }
    get types() {
        return this.acceptTypes.map((t) => '.' + t).join(', ');
    }
    get accept() {
        return this.acceptTypes.map((t) => '.' + t).join(',');
    }
    get empty() {
        return !this.fileControl?.value?.id;
    }
    get demoUrl() {
        return this._sanitizer.bypassSecurityTrustUrl(this.demoUrlObject);
    }
    get hasError() {
        return this.nameControl?.touched && this.nameControl?.invalid;
    }
    toByteNotation(size) {
        return size > 500000 ? Math.round(size / 100000) / 10 + ' MB' : Math.round(size / 1000) + ' kB';
    }
    _maxFileSizeExceeded(maxFileSize) {
        const fileControl = this.fileControl;
        const maxFileSizeExceededFn = () => {
            const file = fileControl?.value?.file;
            return !file || file.size < maxFileSize
                ? null
                : { 'max-file-size-exceeded': { size: file.size, max: maxFileSize } };
        };
        return maxFileSizeExceededFn;
    }
    _fileTypeValidator(types, formattedTypes) {
        const customFormImageTypesFn = (control) => {
            const fileName = control.value;
            if (!fileName) {
                return null;
            }
            const type = fileName.substring(fileName.lastIndexOf('.') + 1);
            if (types.includes(type.toLowerCase())) {
                return null;
            }
            return { 'incorrect-file-type': { type, expectedTypes: formattedTypes } };
        };
        return customFormImageTypesFn;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileValueEditComponent, deps: [{ token: i1.HttpClient }, { token: i2.UrlTransformerService }, { token: i3.DomSanitizer }, { token: i0.ChangeDetectorRef }, { token: i4.Configuration, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: FileValueEditComponent, selector: "ax-file-value-edit", inputs: { fileControl: "fileControl", nameControl: "nameControl", label: "label", hint: "hint", acceptTypes: "acceptTypes", maxFileSize: "maxFileSize", uploadLink: "uploadLink", required: "required", preview: "preview", previewUrl: "previewUrl", demo: "demo", readonly: "readonly", subscriptSizing: "subscriptSizing" }, outputs: { clearedValue: "clearedValue", uploadedFile: "uploadedFile" }, viewQueries: [{ propertyName: "fileSelect", first: true, predicate: ["fileSelect"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<mat-form-field\n  disabled\n  class=\"c-input\"\n  [ngClass]=\"{'remove-subtext': !hasError && !hint && !uploading, readonly: readonly}\"\n  appearance=\"outline\"\n  floatLabel=\"always\"\n  [subscriptSizing]=\"subscriptSizing\"\n>\n  <mat-label *ngIf=\"label\">{{ label }}</mat-label>\n  <input\n    *ngIf=\"nameControl\"\n    matInput\n    [formControl]=\"nameControl\"\n    [placeholder]=\"types\"\n    readonly\n    (click)=\"selectFile()\"\n  />\n  <mat-hint *ngIf=\"uploading\">{{ 'file-edit.uploading' | translate }}</mat-hint>\n  <mat-hint *ngIf=\"!uploading\" class=\"hint\" align=\"end\">{{ hint }} </mat-hint>\n  <mat-error *ngIf=\"fileUploadFailed\">\n    <ax-icon class=\"icon\" name=\"alert-circle\"></ax-icon>\n    {{ 'file-edit.upload-failed' | translate }}\n  </mat-error>\n  <mat-error *ngIf=\"fileTypeError && !fileUploadFailed\">\n    <ax-icon class=\"icon\" name=\"alert-circle\"></ax-icon>\n    {{ 'file-edit.error.incorrect-file-type' | translate: {types: fileTypeError.expectedTypes} }}\n  </mat-error>\n  <mat-error *ngIf=\"fileSizeError && !fileUploadFailed && !fileTypeError\">\n    <ax-icon class=\"icon\" name=\"alert-circle\"></ax-icon>\n    {{\n      ('file-edit.error.max-file-size' | translate) +\n        ' ' +\n        toByteNotation(fileSizeError.max) +\n        ' (' +\n        toByteNotation(fileSizeError.size) +\n        ')'\n    }}\n  </mat-error>\n  <mat-error *ngIf=\"requiredError && !fileSizeError && !fileUploadFailed && !fileTypeError\">\n    {{ 'property.validation.required' | translate: {propertyType: label} }}\n  </mat-error>\n  <ax-image-preview-button\n    *ngIf=\"preview && !empty\"\n    class=\"preview\"\n    matSuffix\n    [source]=\"demo ? demoUrl : (source$ | async)\"\n    [name]=\"nameControl?.value\"\n  ></ax-image-preview-button>\n  @if (!readonly && nameControl?.enabled && nameControl?.value) {\n    <button\n      matSuffix\n      axButton\n      icon-button\n      type=\"button\"\n      (click)=\"clearValue($event)\"\n      [ariaLabel]=\"'label.clear' | translate\"\n    >\n      <ax-icon class=\"icon\" name=\"close\"></ax-icon>\n    </button>\n  }\n</mat-form-field>\n\n@if (!readonly) {\n  <button\n    class=\"clip\"\n    mat-mini-fab\n    (click)=\"selectFile()\"\n    type=\"button\"\n    [ariaLabel]=\"'label.upload' | translate\"\n    [disabled]=\"uploading || nameControl?.disabled\"\n  >\n    <ax-icon class=\"icon paperclip\" name=\"paperclip\"></ax-icon>\n  </button>\n}\n\n<input\n  hidden\n  name=\"file\"\n  type=\"file\"\n  (change)=\"fileSelected($event)\"\n  [attr.accept]=\"accept\"\n  #fileSelect\n/>\n", styles: [":host{display:flex;position:relative}.clip{margin:10px 0 0 15px}.clip .icon{color:#fff}.clip .icon.paperclip{margin:0}\n"], dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i7.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i7.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i7.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i8.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl],      input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i9.MatMiniFabButton, selector: "button[mat-mini-fab]", exportAs: ["matButton"] }, { kind: "component", type: i10.IconComponent, selector: "ax-icon", inputs: ["name", "inline"] }, { kind: "directive", type: i11.ButtonDirective, selector: "[axButton]", inputs: ["color", "labelHideMobile", "smallButton", "bigButton", "fullWidth", "filled", "outline", "icon-button", "hoverLabel", "hover", "lowercase", "disabled"] }, { kind: "component", type: i12.ImagePreviewButtonComponent, selector: "ax-image-preview-button", inputs: ["source", "name"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i13.TranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileValueEditComponent, decorators: [{
            type: Component,
            args: [{ selector: 'ax-file-value-edit', template: "<mat-form-field\n  disabled\n  class=\"c-input\"\n  [ngClass]=\"{'remove-subtext': !hasError && !hint && !uploading, readonly: readonly}\"\n  appearance=\"outline\"\n  floatLabel=\"always\"\n  [subscriptSizing]=\"subscriptSizing\"\n>\n  <mat-label *ngIf=\"label\">{{ label }}</mat-label>\n  <input\n    *ngIf=\"nameControl\"\n    matInput\n    [formControl]=\"nameControl\"\n    [placeholder]=\"types\"\n    readonly\n    (click)=\"selectFile()\"\n  />\n  <mat-hint *ngIf=\"uploading\">{{ 'file-edit.uploading' | translate }}</mat-hint>\n  <mat-hint *ngIf=\"!uploading\" class=\"hint\" align=\"end\">{{ hint }} </mat-hint>\n  <mat-error *ngIf=\"fileUploadFailed\">\n    <ax-icon class=\"icon\" name=\"alert-circle\"></ax-icon>\n    {{ 'file-edit.upload-failed' | translate }}\n  </mat-error>\n  <mat-error *ngIf=\"fileTypeError && !fileUploadFailed\">\n    <ax-icon class=\"icon\" name=\"alert-circle\"></ax-icon>\n    {{ 'file-edit.error.incorrect-file-type' | translate: {types: fileTypeError.expectedTypes} }}\n  </mat-error>\n  <mat-error *ngIf=\"fileSizeError && !fileUploadFailed && !fileTypeError\">\n    <ax-icon class=\"icon\" name=\"alert-circle\"></ax-icon>\n    {{\n      ('file-edit.error.max-file-size' | translate) +\n        ' ' +\n        toByteNotation(fileSizeError.max) +\n        ' (' +\n        toByteNotation(fileSizeError.size) +\n        ')'\n    }}\n  </mat-error>\n  <mat-error *ngIf=\"requiredError && !fileSizeError && !fileUploadFailed && !fileTypeError\">\n    {{ 'property.validation.required' | translate: {propertyType: label} }}\n  </mat-error>\n  <ax-image-preview-button\n    *ngIf=\"preview && !empty\"\n    class=\"preview\"\n    matSuffix\n    [source]=\"demo ? demoUrl : (source$ | async)\"\n    [name]=\"nameControl?.value\"\n  ></ax-image-preview-button>\n  @if (!readonly && nameControl?.enabled && nameControl?.value) {\n    <button\n      matSuffix\n      axButton\n      icon-button\n      type=\"button\"\n      (click)=\"clearValue($event)\"\n      [ariaLabel]=\"'label.clear' | translate\"\n    >\n      <ax-icon class=\"icon\" name=\"close\"></ax-icon>\n    </button>\n  }\n</mat-form-field>\n\n@if (!readonly) {\n  <button\n    class=\"clip\"\n    mat-mini-fab\n    (click)=\"selectFile()\"\n    type=\"button\"\n    [ariaLabel]=\"'label.upload' | translate\"\n    [disabled]=\"uploading || nameControl?.disabled\"\n  >\n    <ax-icon class=\"icon paperclip\" name=\"paperclip\"></ax-icon>\n  </button>\n}\n\n<input\n  hidden\n  name=\"file\"\n  type=\"file\"\n  (change)=\"fileSelected($event)\"\n  [attr.accept]=\"accept\"\n  #fileSelect\n/>\n", styles: [":host{display:flex;position:relative}.clip{margin:10px 0 0 15px}.clip .icon{color:#fff}.clip .icon.paperclip{margin:0}\n"] }]
        }], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.UrlTransformerService }, { type: i3.DomSanitizer }, { type: i0.ChangeDetectorRef }, { type: i4.Configuration, decorators: [{
                    type: Optional
                }] }], propDecorators: { fileControl: [{
                type: Input
            }], nameControl: [{
                type: Input
            }], label: [{
                type: Input
            }], hint: [{
                type: Input
            }], acceptTypes: [{
                type: Input
            }], maxFileSize: [{
                type: Input
            }], uploadLink: [{
                type: Input
            }], required: [{
                type: Input
            }], preview: [{
                type: Input
            }], previewUrl: [{
                type: Input
            }], demo: [{
                type: Input
            }], readonly: [{
                type: Input
            }], subscriptSizing: [{
                type: Input
            }], clearedValue: [{
                type: Output
            }], uploadedFile: [{
                type: Output
            }], fileSelect: [{
                type: ViewChild,
                args: ['fileSelect']
            }] } });

class FileValueEditModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileValueEditModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: FileValueEditModule, declarations: [FileValueEditComponent], imports: [CommonModule,
            FormsModule,
            ReactiveFormsModule,
            MatFormFieldModule,
            MatInputModule,
            MatButtonModule,
            IconsModule,
            TranslatePipe,
            ButtonModule,
            ImagePreviewButtonModule], exports: [FileValueEditComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileValueEditModule, imports: [CommonModule,
            FormsModule,
            ReactiveFormsModule,
            MatFormFieldModule,
            MatInputModule,
            MatButtonModule,
            IconsModule,
            ButtonModule,
            ImagePreviewButtonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileValueEditModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [FileValueEditComponent],
                    imports: [
                        CommonModule,
                        FormsModule,
                        ReactiveFormsModule,
                        MatFormFieldModule,
                        MatInputModule,
                        MatButtonModule,
                        IconsModule,
                        TranslatePipe,
                        ButtonModule,
                        ImagePreviewButtonModule,
                    ],
                    exports: [FileValueEditComponent],
                }]
        }] });

/**
 * Generated bundle index. Do not edit.
 */

export { FILE_TYPES, FileValueEditComponent, FileValueEditModule };
//# sourceMappingURL=aztrix-components-file-value-edit.mjs.map
