import { ChangeDetectorRef, Component, Input, OnInit, Output } from '@angular/core';
import { DriveFile } from 'src/app/components/resource-page/drive-window/drive-layout/drive-file';

type FileRowSelectedEnum = 'selected' | 'indeterminate' | 'empty';

interface FileRow {
  file?: DriveFile;
  name: string;
  path: string;
  parent?: FileRow;
  children?: FileRow[];
  size: number;
  selected: FileRowSelectedEnum;
  status: 'not-started' | 'loading' | 'done' | 'error-while-loading' | 'error';
  type: 'file' | 'folder';
  parentComponent: FileRowComponent;

  changeFileSelection?: (
    selected: FileRowSelectedEnum | 'auto',
    fileRow: FileRow,
    onlyProcessChildren: boolean
  ) => void;
}

@Component({
  selector: 'app-file-row',
  templateUrl: './file-row.component.html',
  styleUrls: ['./file-row.component.scss'],
})
export class FileRowComponent implements OnInit {
  @Input() data?: FileRow;
  @Input() depth?: number = 0;
  @Input() parentComponent?: FileRowComponent;

  // size: number = 0;

  // public thisComponent = this;

  isOpen = true;
  isContentLoaded = false;

  spaceholders = [];

  // public size = data.children; // .reduce()

  constructor() {}

  ngOnInit(): void {
    this.data.changeFileSelection = this.changeFileSelection;
    // creates an array for spaceholders to *ngFor in
    this.spaceholders = new Array(this.depth).fill(1).map((x, i) => i + 1); // [1,2,3,4...]
    if (this.depth > 0) {
      this.isOpen = false;
    }
    // this.size = this.data.size;
    // if (this.size) {
    //   this.incrementSize(this.data.size);
    // }
    this.isContentLoaded = true;
  }

  /**
   * Handles checkbox click event.
   *
   * Calls itself recursively on children
   *
   * @param selected sets this.data.selected. Calculates new value on 'auto'
   * @param fileRow given fileRow
   * @param onlyProcessChildren only sets children 'selected' value recursively
   */
  public changeFileSelection = (
    selected: FileRowSelectedEnum | 'auto',
    fileRow: FileRow,
    onlyProcessChildren: boolean = false
  ) => {
    // calculates new value of selected when 'auto'
    const calcSelected = (selected: FileRowSelectedEnum | 'auto') => {
      if (selected === 'auto') {
        switch (fileRow.selected) {
          case 'selected':
            return 'empty';
            break;
          case 'indeterminate':
            return 'selected';
            break;
          case 'empty':
            return 'selected';
            break;
          // default
        }
      } else {
        return selected;
      }
    };

    const newSelected = calcSelected(selected);

    fileRow.selected = newSelected;
    // set children.selected to newSelected
    if (fileRow?.children?.length) {
      fileRow.children.map((child) => {
        this.changeFileSelection(newSelected, child, true);
      });
    }
    // recalculates parent selected values
    if (!onlyProcessChildren && fileRow?.parent) {
      this.recalcSelected(fileRow.parent);
    }
  };

  // recalculates parent selected values based on their children
  // calls itself recursively on parent if needed

  /**
   * recalculates parent selected values based on their children
   *
   * calls itself recursively on parent if needed
   */
  recalcSelected = (fileRow: FileRow) => {
    const prevSelectedValue = fileRow.selected;

    let selectedNumber = 0;
    let emptyNumber = 0;
    let indeterminateNumber = 0;

    for (let i = 0; i < fileRow.children.length; i++) {
      switch (fileRow.children[i].selected) {
        case 'selected':
          selectedNumber++;
          break;
        case 'empty':
          emptyNumber++;
          break;
        case 'indeterminate':
          indeterminateNumber++;
          break;
        // default;
      }
    }

    let newSelectedValue = prevSelectedValue;
    if ((selectedNumber && emptyNumber) || indeterminateNumber) {
      newSelectedValue = 'indeterminate';
    } else if (selectedNumber) {
      newSelectedValue = 'selected';
    } else if (emptyNumber) {
      newSelectedValue = 'empty';
    } else {
      console.warn('Program cant go in here');
    }
    fileRow.selected = newSelectedValue;

    if (newSelectedValue !== prevSelectedValue && fileRow?.parent) {
      this.recalcSelected(fileRow.parent);
    }
  };

  toggleFolder = () => {
    this.isOpen = !this.isOpen;
  };
}
