import { Component, HostBinding, HostListener, Input, OnInit, Renderer2, Type } from '@angular/core';
import { NbCalendarCell, NbCalendarRange, NbCalendarRangeYearCellComponent, NbCalendarSize, NbCalendarViewMode, NbCalendarViewModeValues, NbCalendarYearModelService, NbDateService, NbPositionedContainerComponent, NbRenderableContainer } from '@nebular/theme';
import { Subject } from 'rxjs';

@Component({
  selector: 'ngx-calendar-view',
  templateUrl: './calendar-view.component.html',
  styleUrls: ['./calendar-view.component.scss']
})
export class CalendarViewComponent extends NbPositionedContainerComponent implements NbRenderableContainer {

  /**
   * Defines active view for calendar.
   * */
  @Input('startView') mode: NbCalendarViewMode = NbCalendarViewMode.DATE;
  static ngAcceptInputType_activeViewMode: NbCalendarViewModeValues;

  /**
   * Determines whether we should show calendar navigation or not.
   * */
  @Input()
  @HostBinding('class.has-navigation')
  showNavigation: boolean = true;

  date: Date;
  visibleDate: Date;
  ViewMode = NbCalendarViewMode;
  max: Date;
  min: Date;
  size: NbCalendarSize = NbCalendarSize.MEDIUM;
  context: contextSetting;
  private listener: any;
  private destroy$: Subject<void> = new Subject<void>();
  constructor(
    protected dateService: NbDateService<Date>,
    private renderer: Renderer2,
    protected yearModelService: NbCalendarYearModelService<Date>,
  ) {
    super();
  }
  renderContent() {

  }
  filter: (Date) => boolean;
  private hasParentClass(child, classname) {
    if (child.className && child.className.split(' ').indexOf(classname) >= 0) return true;
    try {
      //Throws TypeError if child doesn't have parent any more
      return child.parentNode && this.hasParentClass(child.parentNode, classname);
    } catch (TypeError) {
      return false;
    }
  }
  ngOnInit() {
    this.date = this.context.date;
    this.visibleDate = this.date ? this.date : this.dateService.today();


    setTimeout(() => {
      this.listener = this.renderer.listen('window', 'click', (e: Event) => {
        //
        let el = (e.target as HTMLElement);
        if (
          this.hasParentClass(el, 'rbjCalendar')
          // el.className.indexOf('rbjCalendar') > -1 ||
          // el.tagName.indexOf('NB-CALENDAR') > -1
        ) {
          this.context.focus();
        } else {
          this.context.hide();
        }
      })
    }, 50);

  }

  ngOnDestroy() {
    if (this.listener) { this.listener(); }
    this.destroy$.next();
    this.destroy$.complete();
  }
  setViewMode(mode: NbCalendarViewMode) {
    this.mode = mode;
  }
  setVisibleDate(date: Date) {

  }

  prevMonth() {
    this.changeVisibleMonth(-1);
  }

  nextMonth() {
    this.changeVisibleMonth(1);
  }

  prevYear() {
    this.changeVisibleYear(-1);
  }

  nextYear() {
    this.changeVisibleYear(1);
  }

  prevYears() {
    this.changeVisibleYears(-1);
  }

  nextYears() {
    this.changeVisibleYears(1);
  }


  navigateNext() {
    switch (this.mode) {
      case NbCalendarViewMode.DATE:
        return this.nextMonth();
      case NbCalendarViewMode.MONTH:
        return this.nextYear();
      case NbCalendarViewMode.YEAR:
        return this.nextYears();
    }
  }
  onChangeViewMode() {
    if (this.mode === NbCalendarViewMode.DATE) {
      return this.setViewMode(NbCalendarViewMode.YEAR);
    }

    this.setViewMode(NbCalendarViewMode.DATE);
  }

  private changeVisibleMonth(direction: number) {
    this.visibleDate = this.dateService.addMonth(this.visibleDate, direction);
  }

  private changeVisibleYear(direction: number) {
    this.visibleDate = this.dateService.addYear(this.visibleDate, direction);
  }

  private changeVisibleYears(direction: number) {
    this.visibleDate = this.dateService.addYear(this.visibleDate, direction * this.yearModelService.getYearsInView());
  }

  navigateToday() {

    this.visibleDate = this.dateService.today();

    this.context.dateChange(this.dateService.today());
  }


  onChange(date: Date) {
    this.context.dateChange(date);
  }

  @HostListener('focus')
  focus() {
    this.context.focus();
  }

  dayCellComponent: Type<NbCalendarCell<Date, NbCalendarRange<Date>>>

  /**
   * Custom month cell component. Have to implement `NbCalendarCell` interface.
   * */
  monthCellComponent: Type<NbCalendarCell<Date, NbCalendarRange<Date>>>;

  /**
   * Custom year cell component. Have to implement `NbCalendarCell` interface.
   * */
  yearCellComponent: Type<NbCalendarCell<Date, NbCalendarRange<Date>>> = NbCalendarRangeYearCellComponent;



}


export interface contextSetting {
  date: Date,
  hide: () => {},
  focus: () => {},
  dateChange: (d: Date) => {};
}