import { preventDefaultAndStopPropagation } from "./file-validation.util";
import { FileUploadState } from "../types";

export class DragHandler {
  private currentState: FileUploadState = FileUploadState.DEFAULT;
  private isDisabledCallback?: () => boolean;

  private stateChangeCallback?: (state: FileUploadState) => void;
  private fileDropCallback?: (files: File[]) => void;
  private errorMessageCallback?: (errorMessage: string) => void;

  constructor() {}

  public setErrorMessage(callback: (errorMessage: string) => void): void {
    this.errorMessageCallback = callback;
  }

  public setIsDisabled(callback: () => boolean): void {
    this.isDisabledCallback = callback;
  }

  public setValuesInDragHandler(state: FileUploadState): void {
    this.currentState = state;
  }

  public onFileDrop(callback: (files: File[]) => void): void {
    this.fileDropCallback = callback;
  }

  public onStateChange(callback: (state: FileUploadState) => void): void {
    this.stateChangeCallback = callback;
  }

  private setState(state: FileUploadState): void {
    if (this.currentState === FileUploadState.DISABLED || this.isDisabledCallback?.()) return;

    this.currentState = state;
    this.stateChangeCallback?.(state);
  }

  public dragEnter(e: DragEvent): void {
    preventDefaultAndStopPropagation(e);
    if (this.currentState === FileUploadState.DISABLED || this.isDisabledCallback?.()) {
      return;
    }

    this.setState(FileUploadState.DRAG);
  }

  public dragLeave(e: DragEvent): void {
    preventDefaultAndStopPropagation(e);
    if (this.currentState === FileUploadState.DISABLED || this.isDisabledCallback?.()) {
      return;
    }
    
    this.setState(FileUploadState.DEFAULT);
  }

  public dragOver(e: DragEvent): void {
    preventDefaultAndStopPropagation(e);
    if (this.currentState === FileUploadState.DISABLED || this.isDisabledCallback?.()) {
      return;
    }
  }

  public drop(e: DragEvent): void {
    preventDefaultAndStopPropagation(e);
    if (this.currentState === FileUploadState.DISABLED || this.isDisabledCallback?.()) {
      return;
    }
    
    this.setState(FileUploadState.DEFAULT);
    this.handleFiles(e);
  }

  public handleDocumentDrop(e: DragEvent): void {
    preventDefaultAndStopPropagation(e);
    if (this.currentState === FileUploadState.DISABLED) return;

    this.setState(FileUploadState.DEFAULT);
  }

  public preventDragOver(e: DragEvent): void {
    preventDefaultAndStopPropagation(e); 
  }

  public preventDrop(e: DragEvent): void {
    preventDefaultAndStopPropagation(e); 
  }

  public handleFiles(e: Event | DragEvent): void {
    preventDefaultAndStopPropagation(e);
    if (this.currentState === FileUploadState.DISABLED || this.isDisabledCallback?.()) return;

    let files: FileList | null = null;

    if ('dataTransfer' in e && e.dataTransfer) {
      files = e.dataTransfer.files;
    }

    if (!files && e.target instanceof HTMLInputElement) {
      files = e.target.files;
    }

    if (files && files.length > 0) {
      const newFiles = Array.from(files);

      this.fileDropCallback?.(newFiles);
    }

    if(e.target instanceof HTMLInputElement) {
      e.target.value = "";
    }
  }
}
