import {Component, ElementRef, Inject, Input, OnInit, ViewChild} from '@angular/core';
import {ApiService, ResourceNotAvailableOfflineError} from '../../../service/api.service';
import { APP_BASE_HREF } from '@angular/common';
import {EditorService} from '../../../service/editor.service';
import {EditorNodeContract} from '../../nodes/EditorNode.contract';
import {HttpClient} from '@angular/common/http';

@Component({
  selector: 'editor-files',
  templateUrl: './files.component.html',
  styleUrls: ['./files.component.scss'],
})
export class FilesComponent extends EditorNodeContract implements OnInit {
  @Input() nodeId: string;
  @Input() editorUUID: string;
  @ViewChild('uploadForm') uploadForm: ElementRef;
  @ViewChild('fileUploader') fileUploader: ElementRef;

  public fileRecords: Array<any> = [];
  public pendingSetup = true;
  public dbRecord: any = {};
  public dirty = false;
  public notAvailableOffline = false;

  public get readonly() {
    return !this.node || !this.editorService.canEdit();
  }

  constructor(
      protected api: ApiService,
      protected http: HttpClient,
      public editorService: EditorService,
      @Inject(APP_BASE_HREF) private baseHref: string
  ) { super(); }

  public isDirty(): boolean | Promise<boolean> {
    return this.dirty;
  }

  public writeChangesToNode(): void | Promise<void> {
    this.node.Value.Mode = 'files';
  }

  public needsLoad(): boolean | Promise<boolean> {
    return this.node && this.pendingSetup;
  }

  public async performLoad(): Promise<void> {
    if ( !this.node.Value ) {
      this.node.Value = {};
    }

    if ( !this.node.Value.Value && !this.readonly ) {
      this.dbRecord = await this.api.createFileGroup(this.page.UUID, this.node.UUID);
      this.fileRecords = this.dbRecord.files;
      this.node.Value.Mode = 'files';
      this.node.Value.Value = this.dbRecord.UUID;
      this.node.value = this.dbRecord.UUID;
      this.dirty = true;
    } else {
      try {
        this.dbRecord = await this.api.getFileGroup(this.page.UUID, this.node.UUID, this.node.Value.Value);
        this.fileRecords = this.dbRecord.files;
        this.notAvailableOffline = false;
      } catch (e) {
        if ( e instanceof ResourceNotAvailableOfflineError ) {
          this.notAvailableOffline = true;
        } else {
          throw e;
        }
      }
    }

    this.pendingSetup = false;
    if ( this.fileUploader ) {
      this.fileUploader.nativeElement.value = null;
    }
  }

  public async performDelete(): Promise<void> {
    await this.api.deleteFileGroup(this.page.UUID, this.node.UUID, this.node.Value.Value);
  }

  ngOnInit() {
    this.editorService = this.editorService.getEditor(this.editorUUID);
    this.editorService.registerNodeEditor(this.nodeId, this).then(() => {

    });
  }

  getApiSubmit() {
    return this.api._build_url(`files/upload/${this.page.UUID}/${this.node.UUID}/${this.node.Value.Value}`);
  }

  onSubmitClick() {
    if ( this.readonly ) {
      return;
    }

    const fileList: FileList = this.fileUploader?.nativeElement?.files;
    if ( !fileList ) {
      return;
    }

    if ( fileList.length > 0 ) {
      const formData: FormData = new FormData();

      // tslint:disable-next-line:prefer-for-of
      for ( let i = 0; i < fileList.length; i += 1 ) {
        const file = fileList[i];
        formData.append(`uploaded_file_${i}`, file, file.name);
      }

      this.http.post(this.getApiSubmit(), formData).subscribe({
        next: data => {
          this.performLoad();
        },
        error: error => {
          console.error(error);
          this.performLoad();
        },
      });
    }
  }

  onFileChange(event) {}

  getReturnUrl() {
    return `${this.baseHref}editor;id=${this.page.UUID}`;
  }

  downloadFile(fileRecord) {
    // tslint:disable-next-line:max-line-length
    window.open(this.api._build_url(`files/${this.page.UUID}/${this.node.UUID}/get/${this.node.Value.Value}/${fileRecord._id}`), '_blank');
  }
}
