import * as i0 from '@angular/core';
import { Injectable, EventEmitter, Directive, Input, Output, ViewChild } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
import { DatePipe } from '@angular/common';
import { BehaviorSubject, Subject } from 'rxjs';
import { isNullOrUndefined, isSameDates } from '@ironsource/fusion-ui/utils';
import * as i3 from '@ironsource/fusion-ui/services/log';
import * as i4 from '@ironsource/fusion-ui/services/unique-id';
import { CalendarType } from '@ironsource/fusion-ui/components/calendar/entities';
import * as i1 from '@ironsource/fusion-ui/components/calendar/common/base';
import { DaterangePresets } from '@ironsource/fusion-ui/components/daterange/entities';
import { ApiBase } from '@ironsource/fusion-ui/components/api-base';
import { takeUntil, map } from 'rxjs/operators';

const DEFAULT_DATE_FORMAT = 'd MMM, y';
const DEFAULT_DATERANGE_PRESET_LIST = [
    DaterangePresets.Today,
    DaterangePresets.Yesterday,
    DaterangePresets.Last7Days,
    DaterangePresets.Last14Days,
    DaterangePresets.Last30Days,
    DaterangePresets.ThisMonth,
    DaterangePresets.LastMonth
];
const DEFAULT_DATERANGE_PRESET_NAMES = {
    [DaterangePresets.Today]: 'Today',
    [DaterangePresets.Yesterday]: 'Yesterday',
    [DaterangePresets.Last3Days]: 'Last 3 days',
    [DaterangePresets.Last7Days]: 'Last 7 days',
    [DaterangePresets.Last14Days]: 'Last 14 days',
    [DaterangePresets.Last30Days]: 'Last 30 days',
    [DaterangePresets.Last60Days]: 'Last 60 days',
    [DaterangePresets.ThisMonth]: 'This month',
    [DaterangePresets.LastMonth]: 'Last month'
};

class DaterangeService {
    constructor(calendarService) {
        this.calendarService = calendarService;
        this.defaultPresetList = DEFAULT_DATERANGE_PRESET_LIST;
        this.presetDateFunctions = {
            [DaterangePresets.Today]: () => {
                const now = this.calendarService.getCurrentDateUTC();
                return {
                    endDate: now,
                    startDate: now
                };
            },
            [DaterangePresets.Yesterday]: () => {
                const now = this.calendarService.getCurrentDateUTC();
                return {
                    endDate: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1),
                    startDate: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1)
                };
            },
            [DaterangePresets.Last3Days]: () => {
                const now = this.calendarService.getCurrentDateUTC();
                return {
                    endDate: now,
                    startDate: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 2)
                };
            },
            [DaterangePresets.Last7Days]: () => {
                const now = this.calendarService.getCurrentDateUTC();
                return {
                    endDate: now,
                    startDate: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 6)
                };
            },
            [DaterangePresets.Last14Days]: () => {
                const now = this.calendarService.getCurrentDateUTC();
                return {
                    endDate: now,
                    startDate: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 13)
                };
            },
            [DaterangePresets.Last30Days]: () => {
                const now = this.calendarService.getCurrentDateUTC();
                return {
                    endDate: now,
                    startDate: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 29)
                };
            },
            [DaterangePresets.ThisMonth]: () => {
                const now = this.calendarService.getCurrentDateUTC();
                return {
                    startDate: new Date(now.getFullYear(), now.getMonth(), 1),
                    endDate: now
                };
            },
            [DaterangePresets.LastMonth]: () => {
                const now = this.calendarService.getCurrentDateUTC();
                return {
                    startDate: new Date(now.getFullYear(), now.getMonth() - 1, 1),
                    endDate: new Date(now.getFullYear(), now.getMonth(), 0)
                };
            },
            [DaterangePresets.Last60Days]: () => {
                const now = this.calendarService.getCurrentDateUTC();
                return {
                    endDate: now,
                    startDate: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 59)
                };
            }
        };
        this.getCurrentDateUTC = function () {
            return this.calendarService.getCurrentDateUTC();
        };
    }
    isCustomPreset(preset) {
        return preset.hasOwnProperty('label') && preset.hasOwnProperty('startDate') && preset.hasOwnProperty('endDate');
    }
    getPresetName(preset) {
        return this.isCustomPreset(preset)
            ? preset.label
            : DEFAULT_DATERANGE_PRESET_NAMES[preset];
    }
    determinePreset(daterange, availablePresets = null, params) {
        if (!availablePresets) {
            availablePresets = this.defaultPresetList;
        }
        if (!daterange || !daterange.startDate || !daterange.endDate) {
            return null;
        }
        return this.getPresetBySelectedDates(daterange, availablePresets);
    }
    getPresetRange(preset, params) {
        return this.isCustomPreset(preset)
            ? {
                startDate: preset.startDate,
                endDate: preset.endDate
            }
            : this.presetDateFunctions[preset]();
    }
    getDefaultRange() {
        return this.presetDateFunctions[DaterangePresets.Last7Days]();
    }
    getFullUTCDate(date = new Date()) {
        return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
    }
    getPresetBySelectedDates(daterange, availablePresets) {
        for (const preset of availablePresets) {
            const presetRange = this.getPresetRange(preset);
            if (this.isSameRange(daterange, presetRange)) {
                return preset;
            }
        }
        return null;
    }
    isSameRange(selectedRange, presetRange) {
        return this.isSameDay(selectedRange.startDate, presetRange.startDate) && this.isSameDay(selectedRange.endDate, presetRange.endDate);
    }
    isSameDay(date1, date2) {
        return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate();
    }
    static { this.ɵfac = function DaterangeService_Factory(t) { return new (t || DaterangeService)(i0.ɵɵinject(i1.CalendarService)); }; }
    static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DaterangeService, factory: DaterangeService.ɵfac, providedIn: 'root' }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DaterangeService, [{
        type: Injectable,
        args: [{
                providedIn: 'root'
            }]
    }], () => [{ type: i1.CalendarService }], null); })();

const DEFAULT_PLACEHOLDER_TEXT = 'Select';

const _c0 = ["overlay"];
const _c1 = ["chipContent"];
const _c2 = ["trigger"];
class DaterangeBaseComponent extends ApiBase {
    set options(value) {
        this.daterangeOptions = { ...value };
        this.onOptionsChanges();
    }
    get options() {
        return this.daterangeOptions;
    }
    get isPresetsShown() {
        return !!this.presetsHeaderTemplate || (Array.isArray(this.daterangeOptions.presets) && !!this.daterangeOptions.presets.length);
    }
    get isSingleDatePicker() {
        return this.options.calendarAmount === 1;
    }
    constructor(
    /** @internal */
    daterangeService, calendarService, elemRef, logService, uniqueIdService) {
        super();
        this.daterangeService = daterangeService;
        this.calendarService = calendarService;
        this.elemRef = elemRef;
        this.logService = logService;
        this.uniqueIdService = uniqueIdService;
        /** @internal */
        this.closed = new EventEmitter();
        /** @internal */
        this.applied = new EventEmitter();
        /** @internal */
        this.daySelected = new EventEmitter();
        /** @internal */
        this.dropdownSelectConfigurations$ = new BehaviorSubject({});
        /** @internal */
        this.isOpen$ = new BehaviorSubject(false);
        /** @internal */
        this.error = '';
        /** @internal */
        this.currentMonths = [];
        /** @internal */
        this.defaultOptions = {
            calendarAmount: 2,
            format: DEFAULT_DATE_FORMAT,
            presets: [],
            size: 'medium'
        };
        /** @internal */
        this.selection = { startDate: null, endDate: null };
        /** @internal */
        this.selectionStarted = null;
        /** @internal */
        this.originalSelection = null;
        /** @internal */
        this.currentPreset = null;
        /** @internal */
        this.overlayAlign$ = new BehaviorSubject('');
        /** @internal */
        this.selected$ = new BehaviorSubject('');
        /** @internal */
        this.defaultPlaceholder = DEFAULT_PLACEHOLDER_TEXT;
        /** @internal for time selector */
        this.fcHasTimeSelector = new FormControl(false);
        /** @internal */
        this.fcStartTime = new FormControl('00:00', [Validators.required]);
        /** @internal */
        this.fcEndTime = new FormControl('23:59', [Validators.required]);
        /** @internal */
        this.inputTimeOptions = { type: 'time', options: { width: '82px', size: 'small' } };
        this.onDestroy$ = new Subject();
        /** @internal */
        this.propagateChange = (_) => { };
        this.defaultOptions.presets = [...this.daterangeService.defaultPresetList];
    }
    ngOnInit() {
        this.contentTemplate = this.chipContent;
        this.id = this.id || `fs-daterange-${this.uniqueIdService.getUniqueId()}`;
        if (!isNullOrUndefined(this.maxDate)) {
            this.originalMaxDate = this.maxDate;
        }
        this.onOptionsChanges();
        this.resetState$
            .asObservable()
            .pipe(takeUntil(this.onDestroy$))
            .subscribe(_ => {
            this.writeValue(null);
            this.propagateChange(null);
        });
    }
    ngOnDestroy() {
        this.resetState$.complete();
        this.onDestroy$.next();
        this.onDestroy$.complete();
    }
    /** @internal */
    changeConfig(val) {
        this.elemRef.nativeElement.style.setProperty('--fu-chip-max-width', val);
    }
    /** @internal */
    valueSelected() {
        return this.selected$
            .asObservable()
            .pipe(map(value => value !== (this.options?.placeholder || DEFAULT_PLACEHOLDER_TEXT)
            ? { value, isSelected: !!value }
            : { value: null, isSelected: false }));
    }
    /** @internal */
    open() {
        this.trigger.nativeElement.click();
    }
    /** @internal */
    selectPreset(preset, cohort) {
        this.selection = this.daterangeService.getPresetRange(preset, cohort);
        this.currentPreset = preset;
        this.initMonth(this.selection.endDate);
    }
    /** @internal */
    getCalendarConfigurations(month) {
        return {
            parentDaterangeId: this.id,
            month,
            minDate: this.minDate,
            maxDate: this.maxDate,
            allowFutureSelection: this.options.allowFutureSelection ?? !this.isSingleDatePicker,
            selection: this.selection,
            calendarType: this.isSingleDatePicker ? CalendarType.DATE_PICKER : CalendarType.DATE_RANGE
        };
    }
    /** @internal */
    toggle() {
        if (!this.isOpen$.getValue() && !this.isComponentDisabled$.getValue()) {
            this.calculateOverlayAlignPosition();
            this.currentPreset = this.determinePreset(this.originalSelection, this.extraParams);
            this.isOpen$.next(!this.isOpen$.getValue());
            this.setPlaceholder({ isOpen: true });
        }
        else {
            this.close();
        }
    }
    /** @internal */
    onOutsideClick(target) {
        // if (this.validateClickOutside(target) && !target.closest('fusion-dropdown-option')) {
        if (this.validateClickOutside(target)) {
            this.close();
        }
    }
    /** @internal */
    apply() {
        if (this.isOpen$.getValue() && this.isTimeSelectorValid()) {
            this.isOpen$.next(false);
            if (this.selection?.endDate) {
                this.selection.endDate;
            }
            this.originalSelection = { ...this.selection };
            this.setPlaceholder({ isOpen: false });
            this.selectionStarted = null;
            this.applied.emit();
            const valueToPropagate = this.isSingleDatePicker
                ? { date: this.originalSelection.startDate }
                : this.originalSelection?.startDate && this.originalSelection?.endDate
                    ? this.setValueToPropagate(this.originalSelection)
                    : null;
            this.selected$.next(this.getCurrentSelectionFormatted());
            this.propagateChange(valueToPropagate);
            this.clearRangeDaysLimit();
        }
    }
    /** @internal */
    close() {
        if (this.isOpen$.getValue()) {
            this.isOpen$.next(false);
            if (!!this.originalSelection?.startDate && !!this.originalSelection?.endDate) {
                this.initMonth(this.originalSelection.endDate);
                this.selectionStarted = null;
                this.selection = { ...this.originalSelection };
            }
            else {
                this.selection = { endDate: null, startDate: null };
            }
            this.clearRangeDaysLimit();
            this.closed.emit();
            this.setPlaceholder({ isOpen: false });
        }
    }
    /** @internal */
    onMonthChange(direction) {
        let newMonth = null;
        switch (direction) {
            case 'next': {
                const lastMonth = this.currentMonths[this.currentMonths.length - 1];
                newMonth = new Date(lastMonth.getFullYear(), lastMonth.getMonth() + 1, lastMonth.getDate());
                this.currentMonths.push(newMonth);
                this.currentMonths.shift();
                break;
            }
            case 'previous': {
                const firstMonth = this.currentMonths[0];
                newMonth = new Date(firstMonth.getFullYear(), firstMonth.getMonth() - 1, firstMonth.getDate());
                this.currentMonths.unshift(newMonth);
                this.currentMonths.pop();
                break;
            }
        }
    }
    /** @internal */
    onSelectDay(day) {
        this.currentPreset = null;
        if (this.selectionStarted &&
            day.date >= this.selectionStarted.date &&
            day.date.getTime() !== this.selectionStarted.date.getTime()) {
            this.onSelectEndDate(day);
        }
        else {
            this.onSelectStartDate(day);
        }
        this.daySelected.emit(this.selection);
        if (this.isSingleDatePicker) {
            this.apply();
        }
    }
    /** @internal */
    getCurrentSelectionFormatted() {
        let textToDisplay = this.daterangeOptions?.placeholder ?? DEFAULT_PLACEHOLDER_TEXT;
        const preset = this.determinePreset(this.originalSelection);
        if (preset && !this.extraParams) {
            textToDisplay = this.daterangeService.getPresetName(preset);
        }
        else if (!!this.originalSelection?.startDate && !!this.originalSelection?.endDate) {
            const datePipe = new DatePipe('en-US');
            const startDate = datePipe.transform(this.originalSelection.startDate, this.options.format);
            const endDate = datePipe.transform(this.originalSelection.endDate, this.options.format);
            const startTime = this.fcHasTimeSelector.value ? this.fcStartTime.value : '';
            const endTime = this.fcHasTimeSelector.value ? this.fcEndTime.value : '';
            textToDisplay = isSameDates(this.originalSelection.startDate, this.originalSelection.endDate)
                ? `${startDate}${startTime ? ' start at  ' + startTime : ''}${endTime ? ' end at ' + endTime : ''}`
                : `${startDate}${startTime ? ' at ' + startTime : ''} - ${endDate}${endTime ? ' at ' + endTime : ''}`;
        }
        this.currentSelectionFormatted = textToDisplay;
        return textToDisplay;
    }
    /** @internal */
    onWriteValue(value) {
        if (value?.date || value?.startDate || value?.endDate) {
            if (this.isSingleDatePicker) {
                if (!value.date || value.startDate || value.endDate) {
                    this.logService.error(new Error('Single Datepicker object should be {date: Date}'));
                }
                else {
                    value.startDate = value.date;
                    value.endDate = value.date;
                }
            }
            if (this.options.withTimeSelect && !!value.startTime && !!value.endTime) {
                this.fcHasTimeSelector.setValue(true);
                this.fcStartTime.setValue(value.startTime);
                this.fcEndTime.setValue(value.endTime);
            }
            this.selection = { ...value };
            if (!!this.selection?.endDate) {
                this.initMonth(this.selection.endDate);
            }
            this.originalSelection = { ...this.selection };
        }
        else {
            this.selection = { endDate: null, startDate: null };
            this.originalSelection = null;
        }
        this.selected$.next(this.getCurrentSelectionFormatted());
        this.setPlaceholder();
    }
    /** @internal */
    setPlaceholder(configurations = {}) {
        this.dropdownSelectConfigurations$.next({
            ...this.dropdownSelectConfigurations$.getValue(),
            placeholder: { value: this.getCurrentSelectionFormatted() },
            ...configurations
        });
    }
    validateClickOutside(target) {
        return !target.closest('td[data-datetime]');
    }
    calculateOverlayAlignPosition() {
        // in case no was calculation yet
        if (this.overlayAlign$.getValue() === '') {
            // do calculation for overlay alight position
            setTimeout(() => {
                this.overlayAlign$.next('right'); // default - align right
                // because it will be put to DOM on next "tick" - use timeout '0'
                const overlayClientRect = this.overlay.nativeElement.getBoundingClientRect();
                const componentClientRect = this.elemRef.nativeElement.getBoundingClientRect();
                if (overlayClientRect.width > componentClientRect.width) {
                    // need check if has a place on left
                    if (!(componentClientRect.x + componentClientRect.width >= overlayClientRect.width)) {
                        this.overlayAlign$.next('left');
                    }
                }
            }, 0);
        }
    }
    determinePreset(range, params) {
        return this.daterangeService.determinePreset(range, this.options.presets, params);
    }
    initMonth(date) {
        this.currentMonths = [];
        for (let i = 0; i < this.options.calendarAmount; i++) {
            const month = new Date(date.getFullYear(), date.getMonth() - i, 1);
            this.currentMonths.unshift(month);
        }
    }
    onOptionsChanges() {
        if (this.daterangeOptions) {
            this.daterangeOptions = Object.assign({}, this.defaultOptions, this.daterangeOptions);
        }
        else {
            this.daterangeOptions = this.defaultOptions;
        }
        if (!isNullOrUndefined(this.daterangeOptions?.overlayAlignPosition)) {
            this.overlayAlign$.next(this.daterangeOptions.overlayAlignPosition);
        }
        this.initMonth(this.calendarService.getCurrentDateUTC());
    }
    onSelectStartDate(day) {
        this.selectionStarted = day;
        this.selection = { startDate: day.date, endDate: day.date };
        this.setRangeDaysLimit();
    }
    onSelectEndDate(day) {
        this.selection = { startDate: this.selectionStarted.date, endDate: day.date };
        this.selectionStarted = null;
        this.clearRangeDaysLimit();
    }
    setRangeDaysLimit() {
        if (!!this.daterangeOptions?.maxDaysInSelectedRange) {
            const rangeMaxEndDate = new Date(this.selection.startDate);
            rangeMaxEndDate.setDate(rangeMaxEndDate.getDate() + (this.daterangeOptions?.maxDaysInSelectedRange - 1));
            this.maxDate = new Date(rangeMaxEndDate);
        }
    }
    clearRangeDaysLimit() {
        if (!!this.daterangeOptions?.maxDaysInSelectedRange) {
            this.maxDate = !isNullOrUndefined(this.originalMaxDate) ? this.originalMaxDate : null;
        }
    }
    isTimeSelectorValid() {
        if (this.options?.withTimeSelect) {
            if (this.fcHasTimeSelector.value) {
                return this.fcStartTime.valid && this.fcEndTime.valid;
            }
        }
        return true;
    }
    setValueToPropagate(value) {
        if (this.fcHasTimeSelector.value) {
            return { ...value, startTime: this.fcStartTime.value, endTime: this.fcEndTime.value };
        }
        else if (this.options.withTimeSelect) {
            return { startDate: value.startDate, endDate: value.endDate };
        }
        return value;
    }
    /** @internal */
    writeValue(value) {
        this.onWriteValue(value);
    }
    /** @internal */
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    /** @internal */
    registerOnTouched() { }
    static { this.ɵfac = function DaterangeBaseComponent_Factory(t) { return new (t || DaterangeBaseComponent)(i0.ɵɵdirectiveInject(DaterangeService), i0.ɵɵdirectiveInject(i1.CalendarService), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i3.LogService), i0.ɵɵdirectiveInject(i4.UniqueIdService)); }; }
    static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: DaterangeBaseComponent, viewQuery: function DaterangeBaseComponent_Query(rf, ctx) { if (rf & 1) {
            i0.ɵɵviewQuery(_c0, 5);
            i0.ɵɵviewQuery(_c1, 7);
            i0.ɵɵviewQuery(_c2, 5);
        } if (rf & 2) {
            let _t;
            i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.overlay = _t.first);
            i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.chipContent = _t.first);
            i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.trigger = _t.first);
        } }, inputs: { id: "id", presetsHeaderTemplate: "presetsHeaderTemplate", minDate: "minDate", maxDate: "maxDate", extraParams: "extraParams", options: "options" }, outputs: { closed: "closed", applied: "applied", daySelected: "daySelected" }, features: [i0.ɵɵInheritDefinitionFeature] }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DaterangeBaseComponent, [{
        type: Directive
    }], () => [{ type: DaterangeService }, { type: i1.CalendarService }, { type: i0.ElementRef }, { type: i3.LogService }, { type: i4.UniqueIdService }], { id: [{
            type: Input
        }], presetsHeaderTemplate: [{
            type: Input
        }], minDate: [{
            type: Input
        }], maxDate: [{
            type: Input
        }], extraParams: [{
            type: Input
        }], options: [{
            type: Input
        }], closed: [{
            type: Output
        }], applied: [{
            type: Output
        }], daySelected: [{
            type: Output
        }], overlay: [{
            type: ViewChild,
            args: ['overlay']
        }], chipContent: [{
            type: ViewChild,
            args: ['chipContent', { static: true }]
        }], trigger: [{
            type: ViewChild,
            args: ['trigger']
        }] }); })();

/**
 * Generated bundle index. Do not edit.
 */

export { DEFAULT_DATERANGE_PRESET_LIST, DEFAULT_DATERANGE_PRESET_NAMES, DEFAULT_DATE_FORMAT, DEFAULT_PLACEHOLDER_TEXT, DaterangeBaseComponent, DaterangeService };
//# sourceMappingURL=ironsource-fusion-ui-components-daterange-common-base.mjs.map
