import { Component, ViewEncapsulation, ChangeDetectionStrategy, OnInit, AfterViewInit, inject, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DateRange } from '../../_shared/utils/util';
import { ControlBaseComponent, FilterValue } from '../control-base.component';
import dayjs from 'dayjs';
import { UntypedFormBuilder, AbstractControl } from '@angular/forms';
import { CalendarView } from '@progress/kendo-angular-dateinputs';
import { FAST_KENDO_COMMON, FAST_PAGE_COMMON } from '../../app.config';
import { PreventableEvent } from '@progress/kendo-angular-dropdowns';
import { HttpClient } from '@angular/common/http';
import { FilterControlService } from '../filter-control.service';
import { FastMultiselectComponent } from '../../_shared/elements/fast-multiselect.component';

@Component({
  selector: 'control-date-range',
  templateUrl: './control-date-range.component.html',
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [CommonModule, FAST_PAGE_COMMON, FAST_KENDO_COMMON]
})
export class ControlDateRangeComponent extends ControlBaseComponent implements OnInit, AfterViewInit {
  @ViewChild('dateMultiselect') dateMultiselect!: FastMultiselectComponent<never>;

  http = inject(HttpClient);
  controlService = inject(FilterControlService);
  fb = inject(UntypedFormBuilder)
  minDate: Date = new Date(1900, 0, 1);

  bottomView: CalendarView;
  topView: CalendarView;
  placeholder: string;

  datepickerType: 'date-short' | 'date-month';

  kendoFormat: string;
  displayFormat: string;
  saveFormat = 'YYYY/MM/DD';

  fromDateCtrl: AbstractControl;
  toDateCtrl: AbstractControl;

  constructor() {
    super();
  }

  ngOnInit(): void {
    super.ngOnInit();

    if (this.controlStyle === 'MonthRange' || this.controlStyle === 'SingleMonth') {
      this.datepickerType = 'date-month';
      this.placeholder = 'Click "+" to add months';
    } else {
      this.datepickerType = 'date-short';
      this.placeholder = 'Click "+" to add dates';
    }

    if (this.controlStyle === 'DateRange' || this.controlStyle === 'MonthRange') {
      const date: Date = dayjs().startOf('day').toDate();
      const fromDateValue: Date = new Date(date.getFullYear(), date.getMonth(), 1);
      const toDateValue: Date = new Date(date.getFullYear(), date.getMonth() + 1, 0);

      this.form.addControl('fromDate', this.fb.control(fromDateValue));
      this.form.addControl('toDate', this.fb.control(toDateValue));

      this.fromDateCtrl = this.form.controls['fromDate'];
      this.toDateCtrl = this.form.controls['toDate'];

      this.mainCtrl.patchValue([]);
    }
  }

  ngAfterViewInit(): void {
    document.querySelectorAll('.multiSelectNoInput .k-input').forEach(elem => {
      if (elem instanceof HTMLInputElement)
        elem.disabled = true;
    })
  }

  addDateRange(): void {
    if (!this.mainCtrl.value)
      this.mainCtrl.patchValue([]);

    //check if newDateRange already exists
    const newDateRange = new DateRange(this.fromDateCtrl.value, this.toDateCtrl.value, this.controlStyle);
    const hasDateAlready = this.mainCtrl.value.findIndex((x: DateRange) => x.isSame(newDateRange)) !== -1;
    if (!hasDateAlready) {
      this.mainCtrl.value.push(newDateRange);
      this.mainCtrl.updateValueAndValidity();
      this.dateMultiselect.onValueChange(this.mainCtrl.value);
      this.valueChanged();
    }
  }

  onDatesOpen(event: PreventableEvent) {
    event.preventDefault();
  }

  fromDateChanged(date: Date) {
    if (date && this.fromDateCtrl.valid) {
      const fromDate = date;
      const newValue: Date = new Date(fromDate.getFullYear(), fromDate.getMonth() + 1, 0);
      this.toDateCtrl.patchValue(newValue);
    }
  }

  getValue(): string {
    let value1: string = null;
    if (this.mainCtrl.valid && this.mainCtrl.value) {
      if (this.controlStyle === 'SingleDate' || this.controlStyle === 'SingleMonth')
        value1 = dayjs(this.mainCtrl.value).startOf('day').format(this.saveFormat);
      else { //date range or month range
        if (this.mainCtrl.value.length > 0) {
          const dateRanges: string[] = [];
          this.mainCtrl.value.forEach((dateRange: DateRange) => {
            const strToPush: string = dateRange.stringValue;
            dateRanges.push(strToPush);
          })
          value1 = dateRanges.join(',');
        }
      }
    }
    return value1;
  }

  getFilterValue(): FilterValue {
    const value1 = this.getValue();
    const preview = this.getPreview();
    const filterValue: FilterValue = { id: 0, name: this.parameterName, filterId: this.filterId, dataSourceId: this.dataSourceId, preview: preview, value1: value1, value2: null }
    return filterValue;
  }

  getPreview(): string {
    let preview: string = null;
    if (this.mainCtrl.valid && this.mainCtrl.value) {
      if (this.controlStyle === 'SingleDate' || this.controlStyle === 'SingleMonth') {
        preview = dayjs(this.mainCtrl.value).format(this.displayFormat);
      } else if (this.mainCtrl.value.length > 0) { //date range or month range
        const rangeStrings: string[] = this.mainCtrl.value.map((dateRange: DateRange) => {
          return dateRange.displayText;
        })
        preview = this.getStringArrayPreview(rangeStrings);
      }
    }
    return preview;
  }

  setFilterValue(param: FilterValue) {
    if (this.controlStyle === 'SingleDate' || this.controlStyle === 'SingleMonth') {
      const newValue: Date = dayjs(param.value1, this.saveFormat).toDate();
      this.mainCtrl.patchValue(newValue);
    }
    else { //date range or month range
      const rangeStrings = param.value1.split(',');
      rangeStrings.forEach(range => {
        const rangeSplit = range.split('-');
        const fromDate: Date = dayjs(rangeSplit[0], this.saveFormat).toDate();
        const toDate: Date = rangeSplit.length > 1 ? dayjs(rangeSplit[1], this.saveFormat).toDate() : fromDate;
        const newDateRange = new DateRange(fromDate, toDate, this.controlStyle);
        this.mainCtrl.value.push(newDateRange);
      })
    }
    this.mainCtrl.updateValueAndValidity();
    this.valueUpdated$.next(null);
    this.dateMultiselect?.onValueChange(this.mainCtrl.value);
    this.myRef.detectChanges();
  }

  resetValue() {
    this.form.markAsUntouched();
    this.form.markAsPristine();

    if (this.controlStyle === 'DateRange' || this.controlStyle === 'MonthRange')
      this.mainCtrl.patchValue([]);
    else
      this.mainCtrl.patchValue(null);

    this.valueUpdated$.next(null);
    this.myRef.detectChanges();
  }

  valueChanged() {
    this.valueUpdated$.next(null);
    this.mainCtrl.markAsTouched();
  }
}
