import { isBeforeOrEqual, isSameDay, iterateMinutes } from '@dvn/alaca/components/dvn-date-picker/date-utils';
import zoneConfig from '@dvn/core/providers/time-zone-provider/time-zones';
import CalendarUtils from '@dvn/core/util/calendar';
import { SozlukApi } from '@dvn/sozluk/api';
import { takvimAvailableTimePickerSelectedDayI18nDefault } from '@dvn/takvim/components/takvim-available-time-picker-selected-day/i18n';
import { generateSlotsForAvailabilities, getTimeFrameOfAvailabilities } from '@dvn/takvim/components/utils';
import { Component, Event, h, Host, Prop, State, Watch } from '@stencil/core';
import moment from 'moment-timezone';
const conflictSourceNames = {
  'google-calendar': 'Google Calendar',
  'microsoft-calendar': 'Microsoft Calendar',
  'mentornity-calendar': 'calendar',
};
export class TakvimAvailableTimePickerSelectedDay {
  constructor() {
    /**
     * Availabilities filtered by the selected date.
     */
    this.availabilitiesForTheSelectedDate = [];
    /**
     * Duration options of the selected date. Used when there are multiple
     * availabilities for the same date with different durations.
     */
    this.durationForTheSelectedDate = [];
    /**
     * Time slots that are generated when duration (if needed)
     * and availabilities are selected.
     */
    this.timeSlots = [];
    /**
     * Custom time values.
     */
    this.isPickingCustomTime = false;
    this.customTime = { hour: 9, minute: 0 };
    this.customDuration = 30;
    /**
     * API related values.
     */
    this.isProgressing = false;
    this.strings = takvimAvailableTimePickerSelectedDayI18nDefault;
    this.durations = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 75, 90, 105, 120];
    this.onSelectSlot = (slot) => {
      this.selectTime.emit({
        availabilityId: slot.availabilityId,
        locationType: slot.locationType,
        startHour: slot.start,
        endHour: slot.end,
      });
    };
    this.onSelectCustomTime = () => {
      const timeZone = this.userSettings.timeZone;
      const date = this.selectedDate;
      const time = this.customTime;
      const timeString = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()} ${time.hour}:${time.minute}`;
      const startHour = moment.tz(timeString, 'D/M/YYYY h:mm', timeZone).toDate();
      const endHour = iterateMinutes(startHour, this.customDuration);
      this.selectTime.emit({ startHour, endHour });
    };
    this.onSelectDuration = async (duration) => {
      const { userId, viewedUserId, calendarConfigId } = this;
      this.selectedDurationAvailabilities = this.availabilitiesForTheSelectedDate.filter(a => a.meetingDuration === duration);
      // get the earliest start time and latest end time of the availabilities to fetch the unavailabilities for that time period
      const { startDate, endDate } = getTimeFrameOfAvailabilities(this.selectedDurationAvailabilities);
      this.isProgressing = true;
      const unavailabilitiesOfCurrentUser = await this.apiTakvim.getUnavailabilitiesOfUser(calendarConfigId, userId, startDate.toISOString(), endDate.toISOString()).catch(e => {
        this.error = e;
      });
      if (!unavailabilitiesOfCurrentUser)
        return;
      const unavailabilitiesOfOtherUser = await this.apiTakvim.getUnavailabilitiesOfUser(calendarConfigId, viewedUserId, startDate.toISOString(), endDate.toISOString()).catch(e => {
        this.error = e;
      }).finally(() => this.isProgressing = false);
      if (!unavailabilitiesOfOtherUser)
        return;
      this.timeSlots = generateSlotsForAvailabilities(this.selectedDurationAvailabilities, unavailabilitiesOfCurrentUser.results, unavailabilitiesOfOtherUser.results);
    };
  }
  componentWillLoad() {
    this.onSelectedDateChange(this.selectedDate);
  }
  onSelectedDateChange(selectedDate) {
    this.selectedDurationAvailabilities = undefined;
    this.timeSlots = [];
    this.isPickingCustomTime = false;
    if (!selectedDate || !this.availabilities) {
      return;
    }
    this.availabilitiesForTheSelectedDate = this.availabilities
      // filter based on the selected date
      .filter(ca => isSameDay(new Date(ca.startDate), selectedDate))
      // sort to show slots in order if there are multiple availabilities with the same duration
      .sort((a, b) => (isBeforeOrEqual(new Date(a.startDate), new Date(b.startDate)) ? -1 : 1));
    if (this.availabilitiesForTheSelectedDate.length === 1) {
      // select the first availability automatically
      this.onSelectDuration(this.availabilitiesForTheSelectedDate[0].meetingDuration);
      return;
    }
    const durationForTheSelectedDate = [];
    this.availabilitiesForTheSelectedDate.forEach(availability => {
      if (!durationForTheSelectedDate.includes(availability.meetingDuration)) {
        durationForTheSelectedDate.push(availability.meetingDuration);
      }
    });
    this.durationForTheSelectedDate = durationForTheSelectedDate;
  }
  ;
  render() {
    const { availabilities, availabilitiesForTheSelectedDate, calenderConfig, durationForTheSelectedDate, isPickingCustomTime, isProgressing, selectedDate, selectedDurationAvailabilities, membershipConfigId, userSettings, timeSlots, strings, } = this;
    const isPickingOneOfAvailabilitiesOfTheSelectedDate = selectedDate && !selectedDurationAvailabilities
      && availabilitiesForTheSelectedDate.length > 1;
    const isPickingTimeSlot = !!selectedDurationAvailabilities;
    // get calendar permissions of the user
    const calendarPermissions = calenderConfig === null || calenderConfig === void 0 ? void 0 : calenderConfig.permissions.find(preference => preference.membershipConfigId === membershipConfigId);
    const { timeZone, dateFormat } = userSettings;
    let zoneName = '';
    zoneConfig.forEach(group => {
      group.zones.forEach(zone => {
        if (timeZone === zone.value) {
          zoneName = `${zone.name} (${CalendarUtils.getZoneAbbr(zone.value)})`;
          // zoneName = zone.name;
        }
      });
    });
    let cardHeader = `${CalendarUtils.format(selectedDate, 'DD MMMM YYYY')}`;
    if (dateFormat === "MM/DD/YYYY") {
      cardHeader = `${CalendarUtils.format(selectedDate, 'MMMM DD YYYY')}`;
    }
    if (!selectedDate || !availabilities) {
      // don't show the title until the availabilities are loaded
      const title = availabilities ? cardHeader : undefined;
      return (h(Host, null,
        h("dvn-card", { extraClass: "selected-day-container", elevation: 0, leaned: true },
          h("dvn-card-header", { title: title, slot: "header", separated: false }),
          h("div", { class: "progress-container" },
            h("dvn-progress", { indefinite: true, tint: "primary" })))));
    }
    return (h(Host, null,
      h("dvn-card", { extraClass: "selected-day-container", elevation: 0, leaned: true },
        h("div", { slot: "header", class: "available-time-picker-date-header p-3 d-flex justify-content-between align-content-center" },
          h("h4", { key: cardHeader, class: "mt-0 mb-0 day-title" }, cardHeader),
          h("span", { class: "text-neutral" },
            h("i", { class: 'uil uil-clock' }),
            zoneName)),
        isProgressing &&
          h("div", { class: "progress-container" },
            h("dvn-progress", { indefinite: true, tint: "primary" })),
        h("div", { class: "custom-time-picker", style: { display: isPickingCustomTime ? 'flex' : 'none' } },
          h("table", null,
            h("tbody", null,
              h("tr", null,
                h("td", null, strings.time),
                h("td", null,
                  h("dvn-time-picker", { hour: this.customTime.hour, minute: this.customTime.minute, optionsContainerMaxHeight: "132px", leaned: true, timeFormat: this.userSettings.timeFormat, onChange: (e) => this.customTime = e.detail }))),
              h("tr", null,
                h("td", null, strings.duration),
                h("td", null,
                  h("dvn-select", { width: "99px", hideCaret: true, hideCheck: true, hideScrollbar: true, value: `${this.customDuration}`, optionsContainerMaxHeight: "112px", leaned: true, onChange: (e) => this.customDuration = Number(e.detail), enableSearch: true }, this.durations.map(minute => (h("dvn-select-option", { value: `${minute}` }, `${minute} ${strings.min}`)))))))),
          h("div", { class: "d-flex justify-content-end mt-2" },
            h("dvn-button", { tint: "primary", onClick: this.onSelectCustomTime }, strings.done),
            h("dvn-button", { tint: "neutral", onClick: () => this.isPickingCustomTime = false }, strings.cancel))),
        h("div", { class: "selected-day-availabilities", style: { display: isPickingCustomTime ? 'none' : 'block' } },
          isPickingOneOfAvailabilitiesOfTheSelectedDate &&
            h("div", { class: "duration-options-container" }, durationForTheSelectedDate.map(duration => (h("dvn-card", { elevation: 0, outlined: true, selectable: true, onClick: () => this.onSelectDuration(duration) }, SozlukApi.build(strings.bookWithDuration, { duration }))))),
          isPickingTimeSlot &&
            h("div", { class: "slots-container" }, timeSlots.map(slot => (h("dvn-card", { key: `${slot.availabilityId}-${slot.start}`, extraClass: "time-slot", elevation: 0, outlined: true, selectable: true, onClick: () => this.onSelectSlot(slot), tint: slot.sessionUserConflict ? 'danger' : undefined },
              CalendarUtils.format(slot.start, 'HH:mm'),
              " - ",
              CalendarUtils.format(slot.end, 'HH:mm'),
              slot.sessionUserConflict &&
                h("div", { class: "session-user-conflict-message mt-1" },
                  h("small", null, SozlukApi.build(strings.conflictsWithCalendar, {
                    meetingName: slot.sessionUserConflict.name,
                    calendarName: conflictSourceNames[slot.sessionUserConflict.source] || '',
                  }))))))),
          (!isPickingOneOfAvailabilitiesOfTheSelectedDate && !isProgressing) &&
            (calendarPermissions.canPickCustomTime
              ? h("dvn-card", { extraClass: "pick-custom-time-button", elevation: 0, outlined: true, selectable: true, onClick: () => this.isPickingCustomTime = true }, strings.pickCustomTime)
              : (timeSlots.length === 0 && h("div", { class: "no-availability-message text-centered mt-3" }, availabilitiesForTheSelectedDate.length
                ? strings.noAvailabilityLeftForDay
                : strings.noAvailabilityForDay)))))));
  }
  static get is() { return "takvim-available-time-picker-selected-day"; }
  static get originalStyleUrls() { return {
    "$": ["takvim-available-time-picker-selected-day.scss"]
  }; }
  static get styleUrls() { return {
    "$": ["takvim-available-time-picker-selected-day.css"]
  }; }
  static get properties() { return {
    "availabilities": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "Availability[]",
        "resolved": "Availability[]",
        "references": {
          "Availability": {
            "location": "import",
            "path": "@dvn/takvim/api/models"
          }
        }
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "calenderConfig": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "CalendarConfig",
        "resolved": "CalendarConfig",
        "references": {
          "CalendarConfig": {
            "location": "import",
            "path": "@dvn/takvim/api/models"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "selectedDate": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "Date",
        "resolved": "Date",
        "references": {
          "Date": {
            "location": "global"
          }
        }
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "userId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "user-id",
      "reflect": false
    },
    "membershipConfigId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "membership-config-id",
      "reflect": false
    },
    "userSettings": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "UserSettings",
        "resolved": "UserSettings",
        "references": {
          "UserSettings": {
            "location": "import",
            "path": "@dvn/kimlik/api/models/UserSettings"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "viewedUserId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "viewed-user-id",
      "reflect": false
    },
    "viewedUserMembershipConfigId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "viewed-user-membership-config-id",
      "reflect": false
    },
    "calendarConfigId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "calendar-config-id",
      "reflect": false
    },
    "apiTakvim": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "TakvimApi",
        "resolved": "TakvimApi",
        "references": {
          "TakvimApi": {
            "location": "import",
            "path": "@dvn/takvim/api/takvimApi"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "strings": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "TakvimAvailableTimePickerSelectedDayI18n",
        "resolved": "TakvimAvailableTimePickerSelectedDayI18n",
        "references": {
          "TakvimAvailableTimePickerSelectedDayI18n": {
            "location": "import",
            "path": "@dvn/takvim/components/takvim-available-time-picker-selected-day/i18n"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "defaultValue": "takvimAvailableTimePickerSelectedDayI18nDefault"
    }
  }; }
  static get states() { return {
    "availabilitiesForTheSelectedDate": {},
    "durationForTheSelectedDate": {},
    "selectedDurationAvailabilities": {},
    "timeSlots": {},
    "isPickingCustomTime": {},
    "customTime": {},
    "customDuration": {},
    "isProgressing": {},
    "error": {}
  }; }
  static get events() { return [{
      "method": "selectTime",
      "name": "selectTime",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "TimeSelection",
        "resolved": "{ startHour: Date; endHour: Date; availabilityId?: string; locationType?: string; }",
        "references": {
          "TimeSelection": {
            "location": "import",
            "path": "@dvn/takvim/components/takvim-available-time-picker-selected-day/events"
          }
        }
      }
    }]; }
  static get watchers() { return [{
      "propName": "selectedDate",
      "methodName": "onSelectedDateChange"
    }]; }
}
