import { Component, EventEmitter, HostBinding, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { DateAdapter } from '@ui/common';
import { BehaviorSubject } from 'rxjs';
import { CalendarIndicator } from './defs';

@Component({
  selector: 'ui-calendar',
  templateUrl: 'ui-calendar.component.html',
  styleUrls: ['ui-calendar.component.scss'],
})
export class UiCalendarComponent {
  today = new Date();

  /* @internal */
  mode$ = new BehaviorSubject<'week' | 'month'>('month');

  @Input()
  @HostBinding('[ngClass]')
  get mode() {
    return this.mode$.value;
  }
  set mode(value) {
    this.mode$.next(value);
  }

  /* @internal */
  selected$ = new BehaviorSubject<Date>(new Date());

  @Input()
  get selected() {
    return this.selected$.value;
  }
  set selected(value: Date) {
    if (!this.dateAdapter.equals({ first: this.selected, second: value, precision: 'day' })) {
      this.selected$.next(value);
    }
  }

  @Output()
  selectedChange = new EventEmitter<Date>();

  /* @internal */
  displayed$ = new BehaviorSubject<Date>(new Date());

  @Input()
  get displayed() {
    return this.displayed$.value;
  }
  set displayed(value: Date) {
    if (!this.dateAdapter.equals({ first: this.displayed, second: value, precision: 'day' })) {
      this.displayed$.next(value);
    }
  }

  @Output()
  displayedChange = new EventEmitter<Date>();

  @Input()
  minDate: Date;

  @Input()
  maxDate: Date;

  /* @internal */
  indicators$ = new BehaviorSubject<CalendarIndicator[]>([]);

  @Input()
  get indicators() {
    return this.indicators$.value;
  }
  set indicators(value) {
    this.indicators$.next(value);
  }

  constructor(public dateAdapter: DateAdapter) {}

  setSelected(selected: Date) {
    this.selected = selected;
    this.selectedChange.next(this.selected);
  }

  setDisplayed(displayed: Date) {
    this.displayed = displayed;
    this.displayedChange.next(this.displayed);
  }

  navigateBack() {
    let nextDate = this.displayed;
    if (this.mode === 'month') {
      nextDate = this.dateAdapter.addCalendarMonths(this.displayed, -1);
    } else if (this.mode === 'week') {
      nextDate = this.dateAdapter.addCalendarDays(this.displayed, -7);
    }
    if (this.minDate && this.minDate <= nextDate) {
      this.setDisplayed(nextDate);
    }
  }

  navigateForth() {
    let nextDate = this.displayed;
    if (this.mode === 'month') {
      nextDate = this.dateAdapter.addCalendarMonths(this.displayed, 1);
    } else if (this.mode === 'week') {
      nextDate = this.dateAdapter.addCalendarDays(this.displayed, 7);
    }
    if (this.maxDate && this.maxDate >= nextDate) {
      this.setDisplayed(nextDate);
    }
  }
}
