import { Maybe } from '@/core';
import {
  Component,
  EventEmitter,
  Input,
  OnChanges,
  OnDestroy,
  Output,
  SimpleChanges,
  ViewChild,
} from '@angular/core';
import { ButtonDirective } from 'primeng/button';
import { FileSelectEvent, FileUpload } from 'primeng/fileupload';
import { onSelectFileArgs } from './model';

@Component({
  selector: 'app-shared-upload-file',
  templateUrl: './upload-file.component.html',
  imports: [FileUpload, ButtonDirective],
})
export class SharedUploadFileComponent implements OnChanges, OnDestroy {
  @Input() loading: boolean = false;
  @Input() name: string = 'file';
  @Input() accept: string = 'image/*';
  @Input() maxSize: Maybe<number> = 5 * 1024 * 1024;
  @Input() error: Maybe<string> = null;
  @Input() hint: Maybe<string> = null;
  @Input() initial_file_url: Maybe<string> = null;

  @Output() onSelect = new EventEmitter<onSelectFileArgs>();

  @ViewChild(FileUpload) uploader?: FileUpload;

  filePreview: Maybe<string> = null;
  private objectUrl: Maybe<string> = null;

  ngOnChanges(changes: SimpleChanges) {
    if ('initial_file_url' in changes && !this.objectUrl) {
      this.filePreview = this.initial_file_url;
    }
  }

  ngAfterViewInit() {
    this.revokeObjectUrl();

    if (this.initial_file_url && !this.objectUrl) {
      this.filePreview = this.initial_file_url;
    }
  }

  ngOnDestroy() {
    this.revokeObjectUrl();
  }

  onSelectedFile($event: FileSelectEvent) {
    const file = $event.files?.[0];
    if (!file) {
      return;
    }
    this.setPreviewFromFile(file);
    const payload = new FormData();
    payload.append(this.name, file, file.name);
    this.onSelect.emit({ data: payload, file });
  }

  onEditFile() {
    this.uploader?.choose();
  }

  onDeleteFilePreview() {
    this.revokeObjectUrl();
    this.filePreview = null;
  }

  private setPreviewFromFile(file: File) {
    this.revokeObjectUrl();
    this.objectUrl = URL.createObjectURL(file);
    this.filePreview = this.objectUrl;
  }

  private revokeObjectUrl() {
    if (!this.objectUrl) {
      return;
    }
    this.filePreview = null;
    URL.revokeObjectURL(this.objectUrl);
    this.objectUrl = null;
  }
}
