import {
  AfterViewInit,
  Component,
  EventEmitter,
  HostListener,
  Input,
  OnChanges,
  OnInit,
  Output,
  QueryList,
  SimpleChanges,
  ViewChildren,
  ViewEncapsulation
} from '@angular/core'
import { HelperService } from 'src/app/services/helper.service'
import { LicenceService } from 'src/app/services/licence.service'
import { globals } from 'src/app/_globals'
import { LibraryClickEmitter } from './models/LibraryClickEmitter'
import { TableClickEmitter } from './models/TableClickEmitter'

@Component({
  selector: 'dc-tree',
  templateUrl: './dc-tree.component.html',
  styleUrls: ['./dc-tree.component.scss'],
  encapsulation: ViewEncapsulation.None,
  standalone: false
})
export class DcTreeComponent implements OnInit, AfterViewInit, OnChanges {
  // REFACTOR NOTICE
  // This component ideally should be used in whole app instead of `clr-tree` being copied again in every component

  @ViewChildren('searchLibTreeInput')
  searchLibInputList: QueryList<any> = new QueryList()

  @Output() tableOnClickEmitter = new EventEmitter<TableClickEmitter>()
  @Output() libraryOnClickEmitter = new EventEmitter<LibraryClickEmitter>()

  @Input() hasColumns: boolean = false
  @Input() paging: boolean = true
  @Input() libraryList: any[] | undefined
  public librariesSearch: string = ''

  public lib: any = ''
  public table: any = ''
  public column: string | undefined

  public librariesPaging: boolean = false

  public licenceState = this.licenceService.licenceState

  constructor(
    private helperService: HelperService,
    private licenceService: LicenceService
  ) {}

  ngOnInit(): void {}

  ngAfterViewInit(): void {
    setTimeout(() => {
      this.searchLibInputList.first.nativeElement.focus()
    })
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.libraryList?.currentValue) {
      if (this.libraryList) {
        this.helperService.displayLibraries(this.libraryList)
      }
    }
  }

  treeOnFilter(array: any, arrToFilter: string) {
    this.helperService.treeOnFilter(array, arrToFilter)
  }

  libraryOnFilter() {
    this.helperService.libraryOnFilter(
      this.libraryList,
      this.librariesSearch,
      'LIBRARYNAME'
    )

    globals.lineage.librariesSearch = this.librariesSearch
  }

  treeNodeClicked(event: any, item: any, tree: any) {
    if (event.target.title === 'Collapse') {
      this.collapseTreeItems(tree, item)
    }
  }

  libraryOnClick(libid: string, library: any, libTreeNode: any) {
    library['inForeground'] = true //When we programatically call this function, we make sure it is visible in the sidebar

    const focusTableSearch = () =>
      setTimeout(() =>
        libTreeNode.contentContainer.nativeElement.parentElement
          .querySelector('input')
          .focus()
      )

    if (!library['tables']) {
      library['loadingTables'] = true

      this.libraryOnClickEmitter.emit({ libid, library, tablesLoaded: false })

      const interval = setInterval(() => {
        if (!library['loadingTables']) {
          focusTableSearch()

          clearInterval(interval)
        }
      }, 500)
    } else {
      library['expanded'] = !library['expanded']

      this.libraryOnClickEmitter.emit({ libid, library, tablesLoaded: true })
    }

    if (library['expanded']) {
      focusTableSearch()
    }

    this.collapseTreeItems(this.libraryList, library)
  }

  public async tableOnClick(tableuri: string, libTable: any, library: any) {
    this.helperService.debounceCall(50, () => {
      if (!this.hasColumns) {
        this.tableOnClickEmitter.emit({
          tableuri,
          libTable,
          library,
          columnsLoaded: false
        })

        return
      }

      if (!libTable['columns']) {
        libTable['expanded'] = !libTable['expanded']
        libTable['loadingColumns'] = true
        this.table = tableuri

        this.tableOnClickEmitter.emit({
          tableuri,
          libTable,
          library,
          columnsLoaded: false
        })
      } else {
        libTable['expanded'] = !libTable['expanded']

        if (libTable['expanded'] === true) {
          this.table = tableuri

          this.tableOnClickEmitter.emit({
            tableuri,
            libTable,
            library,
            columnsLoaded: true
          })
        }
      }

      this.collapseTreeItems(library['tables'], libTable)
    })
  }

  columnOnClick(libColumn: any, library: any, libTable: any) {
    this.lib = library.LIBRARYID
    this.table = libTable.TABLEURI
    this.column = libColumn.COLURI
  }

  public libTabActive(library: string, table: string) {
    if (!this.lib || !this.table) {
      return false
    }

    return library === this.lib && table === this.table
  }

  public libColumnActive(libColumnUri: string) {
    if (!this.column) {
      return false
    }

    let splitedLibColumnUri = libColumnUri.split('\\')
    let splitedColumnUri = this.column.split('\\')

    return (
      splitedLibColumnUri[splitedLibColumnUri.length - 1] ==
      splitedColumnUri[splitedColumnUri.length - 1]
    )
  }

  public collapseTreeItems(tree: any, itemToSkip: any) {
    tree.forEach((item: any) => {
      if (JSON.stringify(item) !== JSON.stringify(itemToSkip)) {
        item['expanded'] = false
      }
    })
  }

  public loadMoreLibraries() {
    if (!this.librariesPaging) {
      this.librariesPaging = true

      this.helperService.displayLibraries(this.libraryList, true)
      this.librariesPaging = false
    }
  }

  @HostListener('scroll', ['$event'])
  handleScroll(event: Event) {
    let element = event.target as HTMLElement

    if (element) {
      // When list scrolled to the bottom, load more libraries
      if (
        element.scrollTop >=
        element.scrollHeight - element.offsetHeight - 10
      ) {
        this.loadMoreLibraries()
      }
    }
  }
}
