import { Component, OnInit } from '@angular/core';
import { DetailsFormBase } from '@objects-view/details-form-base';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { ContainersApiService } from '@fleio-api/openstack/object-store/containers/containers-api.service';
import { ActivatedRoute, Router } from '@angular/router';
import { ConfigService } from '@shared/config/config.service';
import { EMPTY, Observable, of } from 'rxjs';
import { IActionResult } from '@objects-view/interfaces/actions/action-result';
import { HttpEvent, HttpEventType } from '@angular/common/http';
import { IImageModel } from '@fleio-api/openstack/model/image.model';
import { ObjectsApiService } from '@fleio-api/openstack/object-store/objects/objects-api.service';
import { NotificationService } from '@shared/ui-api/notification.service';
import { catchError } from 'rxjs/operators';
import { IContainerModel } from '@fleio-api/openstack/object-store/model/container.model';
import { IAccountCapabilitiesModel } from '@fleio-api/openstack/object-store/model/account-capabilities.model';

@Component({
  selector: 'app-container-object-upload-form',
  templateUrl: './container-object-upload-form.component.html',
  styleUrls: ['./container-object-upload-form.component.scss'],
  providers: [ObjectsApiService],
})
export class ContainerObjectUploadFormComponent extends DetailsFormBase<IContainerModel> implements OnInit {
  objectUploadForm: UntypedFormGroup;

  file: File;
  uploading = false;
  uploadProgress = 7;
  path: string;
  fileName: string;
  maxObjectNameLength = 1024;

  constructor(
    private formBuilder: UntypedFormBuilder,
    private containersApiService: ContainersApiService,
    private router: Router,
    private config: ConfigService,
    private objectApi: ObjectsApiService,
    private notificationService: NotificationService,
    private activatedRoute: ActivatedRoute,
  ) {
    super();
  }

  createObjectUploadForm(): UntypedFormGroup {
    return this.formBuilder.group({
      file: ['', Validators.required],
      name: ['', [Validators.required, Validators.maxLength(this.maxObjectNameLength)]],
    });
  }

  ngOnInit() {
    super.ngOnInit();
    if (this.objectController) {
      this.objectController.actionCallback = () => this.containerActions();
      const capabilities: IAccountCapabilitiesModel = this.objectController.additionalObjects?.capabilities;
      if (capabilities) {
        this.maxObjectNameLength = capabilities.swift.max_object_name_length ||
          capabilities.swift.max_object_name_size || 1024;
      }
    }

    this.objectUploadForm = this.createObjectUploadForm();

    if (this.object) {
      const additionalQueryParams = Object.assign(
        {}, {container: this.object.id}, this.activatedRoute.snapshot.queryParams,
      );
      this.objectApi.setAdditionalQueryParams(additionalQueryParams);
    }

    this.path = this.activatedRoute.snapshot.queryParams?.path || '';
    this.fileName = this.activatedRoute.snapshot.queryParams?.fileName || '';

    if (this.fileName) {
      this.objectUploadForm.controls.name.setValue(this.fileName);
      this.objectUploadForm.controls.name.disable();
    }
  }

  fileChanged($event: Event) {
    const files = ($event.target as HTMLInputElement).files;
    this.file = files.length > 0 ? files[0] : null;
    const fileName = this.file ? this.file.name : null;
    this.objectUploadForm.controls.file.setValue(fileName);
    if (!this.fileName) {
      this.objectUploadForm.controls.name.setValue(fileName);
    }
  }


  containerActions(): Observable<IActionResult> {
    this.validate();
    if (this.formGroup.invalid) {
      this.displayControlErrors();
      return EMPTY;
    }

    const objectData = this.objectUploadForm.value;
    objectData.path = this.path;
    if (this.fileName) {
      objectData.name = this.fileName;
    }
    if (objectData.file) {
      delete objectData.file;
    }
    const formData = new FormData();
    Object.keys(objectData).map(fieldName => {
      formData.append(fieldName, objectData[fieldName]);
    });
    formData.append('file', this.file, this.file.name);

    const request = this.objectApi.createWithUpload(formData);

    this.objectController.loading = true;
    const response = request.pipe(catchError((error) => {
      this.objectController.loading = false;
      if (error.error) {
        this.setErrors(error.error);
        return EMPTY;
      } else {
        throw error;
      }
    }));

    if (response !== EMPTY) {
      this.uploading = true;
      response.subscribe((data) => {
        let requestCompleted = false;
        const event = data as HttpEvent<IImageModel>;
        if (event.type === HttpEventType.UploadProgress) {
          this.uploadProgress = event.loaded / event.total * 100;
        }

        if (event.type === HttpEventType.Response) {
          requestCompleted = true;
        }

        if (requestCompleted) {
          this.uploading = false;
          this.notificationService.showMessage($localize`File uploaded`);
          const returnUrl = this.config.getPanelUrl(`openstack/object-store/${this.object.id}`);
          const queryParams: { [key: string]: any } = {fileName: undefined};
          if (this.path) {
            queryParams.path = this.path;
          }
          this.router.navigate([returnUrl], {queryParams, queryParamsHandling: 'merge'}).catch(() => {
          });
        }
      });
    }

    return of(null);
  }
}
