import {
  Component,
  ChangeDetectionStrategy,
  Input,
  ElementRef,
  ViewChild,
  OnChanges,
  ChangeDetectorRef,
  AfterViewInit,
  OnDestroy,
  OnInit,
  Output,
  EventEmitter,
  Renderer2,
} from '@angular/core';
import { SelectFilter, SelectFilterOption } from '../../../models';
import { interval, Subscription } from 'rxjs';
import { FilterGroup } from '../../filter-group';

@Component({
  selector: 'ui-select-filter',
  templateUrl: 'select-filter.component.html',
  styleUrls: ['select-filter.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UiSelectFilterComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
  @Output() category = new EventEmitter<SelectFilter>();

  @Input()
  filter: SelectFilter;

  @Input() selectionContainer: ElementRef;

  @Input() module: 'Customer' | 'Branch' = 'Branch';

  @ViewChild('optionsContainer')
  optionsContainer: ElementRef;

  @ViewChild('selectFilter')
  selectFilter: ElementRef;

  canScroll = false;
  scrollPositionPersantage = 0;
  scrollHeightBreakpoint = false;
  maxHeightMargin = 220;

  updateScrollPositionPersantageIntervalSub: Subscription;

  constructor(protected cdr: ChangeDetectorRef, public filterGroup: FilterGroup, private renderer: Renderer2) {}

  ngOnInit() {
    this.filterGroup.updateView.subscribe((_) => this.cdr.markForCheck());
  }

  ngOnDestroy(): void {
    if (this.updateScrollPositionPersantageIntervalSub) {
      this.updateScrollPositionPersantageIntervalSub.unsubscribe();
    }
  }

  ngAfterViewInit(): void {
    this.updateScrollButton();
    this.updateScrollPositionPersantageIntervalSub = interval(500).subscribe(() => this.updateScrollButton());
  }

  updateScrollButton() {
    this.updateHeight();
    this.updateScrollPositionPersantage();
    this.setCanScroll();
    this.cdr.markForCheck();
  }

  setCanScroll() {
    if (this.optionsContainer) {
      const container = this.optionsContainer.nativeElement;
      const scrollHeight = container.scrollHeight;
      const height = container.clientHeight;
      if (this.canScroll !== scrollHeight > height) {
        this.canScroll = scrollHeight > height;
        this.cdr.markForCheck();
      }
    }
  }

  ngOnChanges(): void {}

  preSelectCategory(category: SelectFilter) {
    this.category.emit(category);
  }

  createSelctFilterOptionContext(option: SelectFilterOption) {
    return { $implicit: option };
  }

  selectAll() {
    this.filterGroup.selectAll(this.filter);
    this.cdr.markForCheck();
  }

  unselectAll() {
    this.filterGroup.unselectAll(this.filter);
    this.cdr.markForCheck();
  }

  updateScrollPositionPersantage() {
    if (this.optionsContainer) {
      const container: HTMLElement = this.optionsContainer.nativeElement;
      const scrollHeight = container.scrollHeight;
      const scrollTop = container.scrollTop;
      const height = container.clientHeight;
      const scrollPositionPersantage = Math.round((100 / (scrollHeight - height)) * scrollTop);
      if (this.scrollPositionPersantage !== scrollPositionPersantage) {
        this.scrollPositionPersantage = scrollPositionPersantage;
        this.cdr.markForCheck();
      }
    }
  }

  scroll() {
    const ele: HTMLElement = this.optionsContainer.nativeElement;
    if (this.scrollPositionPersantage >= 20) {
      ele.scrollTo({ top: 0, behavior: 'smooth' });
    } else {
      ele.scrollTo({ top: ele.scrollHeight, behavior: 'smooth' });
    }
  }

  updateHeight() {
    if (this.selectionContainer) {
      if (this.scrollPositionPersantage === 100) {
        this.renderer.setStyle(this.optionsContainer.nativeElement, 'margin-bottom', `${-100}px`);
        this.renderer.setStyle(this.optionsContainer.nativeElement, 'bottom', `${100}px`);
      } else {
        this.renderer.setStyle(this.optionsContainer.nativeElement, 'margin-bottom', `${0}px`);
        this.renderer.setStyle(this.optionsContainer.nativeElement, 'bottom', `auto`);
      }

      const height = window.innerHeight - this.selectionContainer.nativeElement.offsetTop - this.maxHeightMargin;

      this.renderer.setStyle(this.optionsContainer.nativeElement, 'max-height', `${height}px`);
      this.cdr.detectChanges();
    }
  }
}
