'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const index = require('./index-1141a245.js');
const ui = require('./ui-924b3658.js');
const index$1 = require('./index-9d3d3d15.js');
const index$2 = require('./index-61f9621a.js');
const Equal = require('./Equal-e7239026.js');
const string = require('./string-de672b69.js');
const User = require('./User-dbfbd45e.js');
const dateUtils = require('./date-utils-86cd43eb.js');
const Availability = require('./Availability-4c8ccc7e.js');
require('./data-model-01c368bc.js');
require('./reference-field-1239b0c3.js');
require('./index-2eea69a0.js');
require('./index-0783d14f.js');
require('./FieldModelGenerator-d61f01d4.js');
require('./index-9fd84b93.js');
const index$4 = require('./index-b776fc14.js');
const DvnDataProvider = require('./DvnDataProvider-d7268155.js');
const dataTransferField = require('./data-transfer-field-e8417d5f.js');
const index$3 = require('./index-a2e99c85.js');
const session = require('./session-f588baa3.js');
require('./apiBase-6c66ff1b.js');
require('./filter-d5040f65.js');
const calendar = require('./calendar-e4b7baeb.js');
const cookie = require('./cookie-e64bc800.js');
const timeZones = require('./time-zones-5b212929.js');
const i18n = require('./i18n-6a8d848d.js');
require('./FieldGenerator-279a646b.js');
require('./BaseField-381327a9.js');
require('./InterceptorHandler-09a1e84b.js');
require('./date-a24d7714.js');
require('./_commonjsHelpers-206db00d.js');
require('./moment-7a3433f2.js');
require('./list-fetch-state-6f8f3bf8.js');
require('./membership-e87e02ed.js');
require('./table-config-969d3038.js');
require('./UserSettings-2a2399b1.js');
require('./index-33e96540.js');
require('./mentorinty-bridge-api-b1eaa56d.js');
require('./index-b7855ed6.js');
require('./attachment-a0cdf203.js');
require('./CalendarConfig-998f742e.js');
require('./sozluk-entries-3b9686e7.js');
require('./i18n-0bcf144d.js');
require('./i18n-77d45414.js');
require('./kimlik-api-663f4884.js');
require('./i18n-a8cc9ef1.js');

const MAX_MONTH_FOR_RECURRENCE = 3;
const lastday = (date) => {
  return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
};
/**
 * Generates the availabilities from the raw availability list by using their recurrence.
 * Recurring availabilities are populated for every week/month until the maxMonthForRecurrence is reached.
 * @param availabilities
 * @param maxMonthForRecurrence
 * @param startDate used for calculating the end month
 */
const generateAvailabilities = (availabilities, unavailabilitiesOfOtherUser = [], maxMonthForRecurrence = MAX_MONTH_FOR_RECURRENCE, startDate = new Date()) => {
  // yesterday midnight
  const minDate = new Date();
  // minDate.setDate(minDate.getDate() - 1)
  minDate.setUTCHours(0, 0, 0, 0);
  const maxDate = dateUtils.iterateMonth(startDate, maxMonthForRecurrence);
  maxDate.setDate(lastday(maxDate)); // last day is the end of the iterated month
  const now = new Date();
  const allAvailabilities = [];
  availabilities.forEach(availability => {
    if (availability.meetingDuration <= 0) {
      return;
    }
    if (availability.recurrence === 'weekly') {
      let baseStartDate = new Date(availability.startDate);
      let baseEndDate = new Date(availability.endDate);
      while (dateUtils.isBefore(baseStartDate, maxDate)) {
        // check if the availability to add is after the minimum date
        // adding this check to the 'while' loop above results ignoring the
        // recurring availability completely if it's created before yesterday
        const isAvailabilityAfterMinDate = dateUtils.isBefore(minDate, baseStartDate);
        const availabilityToAdd = Availability.Availability.decode(Object.assign(Object.assign({}, availability), { startDate: baseStartDate.toISOString(), endDate: baseEndDate.toISOString() }));
        // check if all slots of the availability are taken or not
        const slots = generateSlotsForAvailability(availabilityToAdd);
        const availableSlots = filterConflictingSlots(slots, [], unavailabilitiesOfOtherUser);
        const isThereAnyAvailableSlotsLeft = availableSlots.length > 0;
        if (isAvailabilityAfterMinDate && isThereAnyAvailableSlotsLeft) {
          allAvailabilities.push(availabilityToAdd);
        }
        baseStartDate = dateUtils.iterateWeek(baseStartDate, 1);
        baseEndDate = dateUtils.iterateWeek(baseEndDate, 1);
      }
    }
    else if (new Date(availability.endDate) >= now) {
      // single
      // check if all slots of the availability are taken or not
      const slots = generateSlotsForAvailability(availability);
      const availableSlots = filterConflictingSlots(slots, [], unavailabilitiesOfOtherUser);
      const isThereAnyAvailableSlotsLeft = availableSlots.length > 0;
      if (isThereAnyAvailableSlotsLeft) {
        allAvailabilities.push(availability);
      }
    }
  });
  return allAvailabilities
    .sort((a, b) => {
    // @ts-ignore
    return new Date(a.startDate) - new Date(b.startDate);
  });
};
/**
 * Returns the earliest start time and latest end time of the given availabilities.
 * @param availabilities
 */
const getTimeFrameOfAvailabilities = (availabilities) => {
  let startDate;
  let endDate;
  availabilities.forEach(availability => {
    if (!startDate || dateUtils.isBefore(new Date(availability.startDate), startDate)) {
      startDate = new Date(availability.startDate);
    }
    if (!endDate || dateUtils.isAfter(new Date(availability.endDate), endDate)) {
      endDate = new Date(availability.endDate);
    }
  });
  return { startDate, endDate };
};
const generateSlotsForAvailabilities = (availabilities = [], unavailabilitiesOfCurrentUser, unavailabilitiesOfOtherUser) => {
  const timeSlots = [];
  availabilities.forEach(availability => {
    const slots = generateSlotsForAvailability(availability);
    timeSlots.push(...filterConflictingSlots(slots, unavailabilitiesOfCurrentUser, unavailabilitiesOfOtherUser));
  });
  return timeSlots;
};
const doTimesIntersect = (start1, end1, start2, end2) => {
  if (dateUtils.isEqual(start1, start2) || dateUtils.isEqual(end1, end2)) {
    return true;
  }
  // s1    e1
  //    s2    e2
  if (dateUtils.isBefore(start1, start2) && dateUtils.isBefore(start2, end1)) {
    return true;
  }
  //    s1    e1
  // s2    e2
  if (dateUtils.isBefore(start2, start1) && dateUtils.isBefore(start1, end2)) {
    return true;
  }
  //    s1  e1
  // s2        e2
  if (dateUtils.isBefore(start2, start1) && dateUtils.isBefore(end1, end2)) {
    return true;
  }
  // s1        e1
  //    s2  e2
  if (dateUtils.isBefore(start1, start2) && dateUtils.isBefore(end2, end1)) {
    return true;
  }
  return false;
};
const generateSlotsForAvailability = (availability) => {
  let slotStart = new Date(availability.startDate);
  let slotEnd = dateUtils.iterateMinutes(slotStart, availability.meetingDuration);
  const availabilityEnd = new Date(availability.endDate);
  const slots = [];
  do {
    slotStart.setSeconds(1);
    slots.push({
      availabilityId: availability._id,
      locationType: availability.locationType,
      start: slotStart,
      end: slotEnd,
    });
    slotStart = dateUtils.iterateMinutes(slotEnd, availability.breakDuration || 0);
    slotEnd = dateUtils.iterateMinutes(slotStart, availability.meetingDuration);
  } while (dateUtils.isBeforeOrEqual(slotEnd, availabilityEnd));
  return slots;
};
const filterConflictingSlots = (slots, unavailabilitiesOfCurrentUser, unavailabilitiesOfOtherUser) => {
  const timeSlots = [];
  slots.forEach(slot => {
    if (new Date(slot.start) < new Date()) {
      return;
    }
    let hasIntersection = false;
    for (let i = 0; i < unavailabilitiesOfOtherUser.length; i++) {
      const unavailability = unavailabilitiesOfOtherUser[i];
      if (doTimesIntersect(slot.start, slot.end, new Date(unavailability.startDate), new Date(unavailability.endDate))) {
        // slot.sessionUserConflict = unavailability.reason;
        hasIntersection = true;
        break;
      }
    }
    if (hasIntersection) {
      return;
    }
    for (let i = 0; i < unavailabilitiesOfCurrentUser.length; i++) {
      const unavailability = unavailabilitiesOfCurrentUser[i];
      if (doTimesIntersect(new Date(slot.start), new Date(slot.end), new Date(unavailability.startDate), new Date(unavailability.endDate))) {
        slot.sessionUserConflict = unavailability.reason;
        break;
      }
    }
    timeSlots.push(slot);
  });
  return timeSlots;
};

class DvnMemberDataAdapter {
  constructor(returnUserId = false) {
    this.returnUserId = returnUserId;
  }
  label(item) {
    return item.user.name;
  }
  value(item) {
    return this.returnUserId ? item.user._id : item._id;
  }
}

const takvimAvailableTimePickerCss = "takvim-available-time-picker.mobile date-picker-container dvn-date-picker{margin-right:0 !important}takvim-available-time-picker.desktop dvn-date-picker{margin-right:1rem !important}takvim-available-time-picker .error-message{color:var(--color-danger);font-size:var(--font-size-large)}";

const meetingLocationTypes = [
  {
    name: 'Custom',
    value: 'custom',
  },
  {
    name: 'Jitsi Meet',
    value: 'jitsi',
  },
  {
    name: 'Zoom',
    value: 'zoom',
  },
  {
    name: 'Google Meet',
    value: 'google',
  },
  {
    name: 'Microsoft Teams',
    value: 'microsoftbusiness',
  },
];
const formErrors = (error) => {
  if (!error)
    return [];
  // TODO show proper error messages from apiSozluk
  return [
    string.capitalize(`${error.data.message.split('-').join(' ')}.`, false),
  ];
};
const TakvimAvailableTimePicker = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.createMeeting = index.createEvent(this, "createMeeting", 7);
    this.storage = new cookie.CookieStorage();
    this.meetingsByMeetingTypes = {};
    /**
     * Raw availabilities fetched from the api.
     */
    this.availabilities = [];
    this.meetingLocationType = 'jitsi';
    this.meetingLocation = '';
    this.isProgressing = true;
    this.weekStartDay = 'monday';
    this.onSizeChange = (size) => {
      this.size = size;
      this.selectedTime = undefined;
      if (this.isMobileUI()) {
        // reset the date otherwise the slot list dialog will pop when switched to mobile
        this.selectedDate = undefined;
      }
      else {
        // set the date otherwise the slot list will keep showing progress
        this.selectedDate = new Date();
      }
    };
    this.isMobileUI = () => this.size < ui.ResponsiveSize.Small;
    this.formFields = () => {
      const { calendarConfig, guests, guestMetadata, meetingsByMeetingTypes, meetingTypes, selectedTime, userSettings, strings, } = this;
      const isMenteeCreateMeeting = !(selectedTime === null || selectedTime === void 0 ? void 0 : selectedTime.locationType);
      const authPlatforms = userSettings.authPlatforms;
      let maxFieldCount = isMenteeCreateMeeting ? 2 : 0;
      const fields = [];
      const availableMeetingTypes = meetingTypes === null || meetingTypes === void 0 ? void 0 : meetingTypes.filter(meetingType => {
        var _a;
        return ((((_a = meetingsByMeetingTypes[meetingType.id]) === null || _a === void 0 ? void 0 : _a.length) || 0) < meetingType.maxCount);
      });
      calendarConfig.guestDefinitions.forEach((guestDefinition, i) => {
        // TODO use the 'membershipFieldIdInTable' in guestDefinition for the relational guests
        const dataConfig = this.dataConfigs.find(dataConfig => dataConfig._id === guestDefinition.tableId);
        const guestIndex = guestMetadata.findIndex(gm => gm.membershipConfigId === guestDefinition.tableId);
        const guest = guests[guestIndex];
        fields.push(new index$1.SingleChoiceField('guest_' + guestDefinition.tableId + '_' + i, i === 0 ? strings.guests : '', undefined, '', 'select', string.capitalize(dataConfig.roleName)).setDataProvider(new DvnDataProvider.DvnDataProvider(this.apiData, guestDefinition.tableId, {}, guest ? [{ user: guest }] : [], {
          fields: [
            { fieldId: 'email' },
            { fieldId: 'firstName' },
            { fieldId: 'lastName' },
          ]
        })).setDataAdapter(new DvnMemberDataAdapter(true))
          .setValue(guest === null || guest === void 0 ? void 0 : guest._id)
          .setDisabled(!!guest)
          .setVisibility(false)
          .setRequired(guestDefinition.minCount > 0));
      });
      if (meetingTypes && meetingTypes.length > 0) {
        maxFieldCount += 1;
        fields.push(new index$1.SingleChoiceField('meetingType', strings.selectSession, availableMeetingTypes.map(meetingType => new index$1.SingleChoiceFieldOption(meetingType.name, meetingType.id)), '', 'select').setErrorTitle('Session').require());
      }
      const meetingLocationTypesLanguage = meetingLocationTypes.map(meetingType => ({
        name: strings[meetingType.value],
        value: meetingType.value,
      }));
      fields.push(...[
        new index$1.SingleChoiceField('locationType', strings.location, meetingLocationTypesLanguage
          // filter out the location types if user doesn't have the corresponding auth platform (zoom, google, microsoftbusiness)
          .filter(locationType => {
          if (locationType.value === 'custom' || locationType.value === 'jitsi') {
            return true;
          }
          return !!authPlatforms.some(authPlatform => authPlatform.id === locationType.value);
        })
          .map(locationType => new index$1.SingleChoiceFieldOption(locationType.name, locationType.value)), '', 'select').setValue(this.storage.get('mt_lt') || (selectedTime === null || selectedTime === void 0 ? void 0 : selectedTime.locationType))
          .setVisibility(isMenteeCreateMeeting)
          .require()
      ]);
      if (isMenteeCreateMeeting) {
        fields.push(...[
          new index$2.TextField('location', strings.meetingLocation)
            .addInterceptor('onFormChange', new Equal.ConcealerConditional(new Equal.Equal('locationType', 'custom')))
            .require()
            .hide()
        ]);
      }
      return { fields, maxFieldCount };
    };
    this.onSelectTime = async (e) => {
      this.selectedTime = e.detail;
      const showMeetingDetailsForm = !!this.selectedDate && !!this.selectedTime;
      this.selectedAvailability = this.availabilities.find(availability => availability._id === e.detail.availabilityId);
      if (showMeetingDetailsForm && !this.meetings && this.meetingTypes) {
        // get the meetings of the users to filter out the meeting types based on the number of meetings they have
        const { viewedUserId, calendarConfigId, userId } = this;
        this.isProgressing = true;
        const meetings = await this.apiTakvim.getMeetingsOfUser(calendarConfigId, [userId, viewedUserId]).catch(e => {
          this.error = e;
        }).finally(() => this.isProgressing = false);
        if (!meetings)
          return;
        this.meetings = meetings.results;
        const meetingsByMeetingTypes = {};
        this.meetings.forEach(meeting => {
          if (meetingsByMeetingTypes[meeting.meetingType]) {
            meetingsByMeetingTypes[meeting.meetingType].push(meeting);
          }
          else {
            meetingsByMeetingTypes[meeting.meetingType] = [meeting];
          }
        });
        this.meetingsByMeetingTypes = meetingsByMeetingTypes;
      }
    };
    this.onSubmitForm = async (event) => {
      var _a, _b, _c;
      const data = event.detail.values;
      const { location, locationType, meetingType } = data;
      const { startHour, endHour, availabilityId } = this.selectedTime;
      const hasMeetingGoals = ((_b = (_a = this.meetingGoalConfig) === null || _a === void 0 ? void 0 : _a.meetingGoals) === null || _b === void 0 ? void 0 : _b.length) > 0;
      const selectedSession = hasMeetingGoals && ((_c = this.meetingGoalConfig) === null || _c === void 0 ? void 0 : _c.meetingGoals.find(goal => goal.identifier === this.meetingType));
      const hasCreationRule = !!((selectedSession === null || selectedSession === void 0 ? void 0 : selectedSession.periodStartDate) || (selectedSession === null || selectedSession === void 0 ? void 0 : selectedSession.periodEndDate));
      const periodStartDate = selectedSession.periodStartDate * 1000;
      const periodEndDate = selectedSession.periodEndDate * 1000;
      const allowToCreateMeeting = periodStartDate <= startHour.getTime() && periodEndDate >= startHour.getTime();
      if (hasCreationRule && !allowToCreateMeeting) {
        this.errorMessage = `${index$3.SozlukApi.build(this.strings.selectMeetingBetween, { startDate: calendar.CalendarUtils.format((selectedSession === null || selectedSession === void 0 ? void 0 : selectedSession.periodStartDate) * 1000, 'DD/MM/YYYY'), endDate: calendar.CalendarUtils.format(selectedSession.periodEndDate * 1000, 'DD/MM/YYYY') })}`;
        return;
      }
      const guestsObject = {};
      const guestsMetadataObject = {};
      Object.keys(data).forEach(fieldId => {
        if (fieldId.startsWith('guest_')) {
          // this is a guest selection in the form. the value is the user id
          const [_, membershipConfigId, index] = fieldId.split('_');
          guestsMetadataObject[index] = { membershipConfigId };
          guestsObject[index] = User.User.generateRef(data[fieldId]);
        }
      });
      const meeting = {
        locations: [{
            address: location,
            type: locationType,
          }],
        meetingType,
        startDate: startHour.toISOString(),
        endDate: endHour.toISOString(),
        // guests: [
        //   User.generateRef(this.viewedUserId),
        //   User.generateRef(this.userId),
        // ],
        guests: Object.values(guestsObject),
        guestMetadata: Object.values(guestsMetadataObject),
        createdBy: User.User.generateRef(this.userId),
        status: 'active',
        calendar: { _ref: 'takvim-calendar-configs', _id: this.calendarConfigId },
      };
      if (availabilityId) {
        meeting.availability = {
          _ref: 'takvim-availabilities',
          _id: availabilityId
        };
      }
      this.createMeetingError = undefined;
      this.isProgressing = true;
      const createMeetingResponse = await this.apiTakvim.createMeeting(meeting).catch(e => {
        this.createMeetingError = e;
      }).finally(() => this.isProgressing = false);
      if (!createMeetingResponse)
        return;
      this.meetings = undefined;
      this.selectedTime = undefined;
      this.meetingType = undefined;
      this.selectedDate = new Date(this.selectedDate.toISOString());
      // store lastest location type = lt
      this.storage.save('mt_lt', locationType);
      this.createMeeting.emit(Object.assign(Object.assign({}, createMeetingResponse), meeting));
    };
    this.displayMeetingDetails = (meetingDetailsFormFields, dialogTitle) => {
      var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
      const timeZone = this.userSettings.timeZone;
      const hourFormat = this.userSettings.timeFormat === '12-hour' ? 'hh:mm A' : 'HH:mm';
      const location = ((_a = this.selectedAvailability) === null || _a === void 0 ? void 0 : _a.locationType) === 'custom' ? (_b = this.selectedAvailability) === null || _b === void 0 ? void 0 : _b.location : `${this.strings[(_c = this.selectedAvailability) === null || _c === void 0 ? void 0 : _c.locationType]}`;
      const isCustom = !((_d = this.selectedTime) === null || _d === void 0 ? void 0 : _d.availabilityId);
      const hasMeetingGoals = ((_f = (_e = this.meetingGoalConfig) === null || _e === void 0 ? void 0 : _e.meetingGoals) === null || _f === void 0 ? void 0 : _f.length) > 0;
      const selectedSession = hasMeetingGoals && ((_g = this.meetingGoalConfig) === null || _g === void 0 ? void 0 : _g.meetingGoals.find(goal => goal.identifier === this.meetingType));
      const hasCreationRule = !!((selectedSession === null || selectedSession === void 0 ? void 0 : selectedSession.periodStartDate) || (selectedSession === null || selectedSession === void 0 ? void 0 : selectedSession.periodEndDate));
      return (index.h("div", { class: "ml-3 mr-3 mt-3" }, this.errorMessage &&
        index.h("p", { class: "error-message" }, this.errorMessage), index.h("h3", { class: "mb-0" }, dialogTitle), index.h("p", { style: { fontWeight: '600' }, class: "mt-0" }, index$4.momentTimezone(this.selectedDate).tz(timeZone).format('MMMM/DD/YYYY, ddd')), index.h("h4", { style: {
          marginBottom: '0'
        } }, index$4.momentTimezone((_h = this.selectedTime) === null || _h === void 0 ? void 0 : _h.startHour).tz(timeZone).format(hourFormat), " - ", index$4.momentTimezone((_j = this.selectedTime) === null || _j === void 0 ? void 0 : _j.endHour).tz(timeZone).format(hourFormat)), index.h("p", { style: {
          color: 'var(--color-neutral)',
          marginTop: '0'
        } }, timeZone, index.h("dvn-icon", { iconName: 'uil uil-clock' })), hasMeetingGoals && selectedSession && hasCreationRule &&
        index.h("div", null, index.h("h4", { style: {
            marginBottom: '0'
          } }, this.strings.allowMeetingCreation), index.h("p", { style: {
            color: 'var(--color-neutral)',
            marginTop: '0'
          } }, calendar.CalendarUtils.format((selectedSession === null || selectedSession === void 0 ? void 0 : selectedSession.periodStartDate) * 1000, 'DD/MM/YYYY'), " - ", calendar.CalendarUtils.format(selectedSession.periodEndDate * 1000, 'DD/MM/YYYY'))), !isCustom && index.h("p", { style: { fontWeight: '600' }, class: "m-0" }, this.strings.location, ": ", location), index.h("doldurma-form", { key: `${(_k = this.selectedTime) === null || _k === void 0 ? void 0 : _k.startHour}-${(_l = this.selectedTime) === null || _l === void 0 ? void 0 : _l.endHour}`, fields: meetingDetailsFormFields, onSubmit: this.onSubmitForm, submitButtonLabel: this.strings.scheduleMeeting, progressing: this.isProgressing, formErrors: formErrors(this.createMeetingError), width: '100%', onChange: (e) => {
          this.meetingType = e.detail.meetingType;
          this.errorMessage = undefined;
        } })));
    };
  }
  async componentWillLoad() {
    this.uiHelper = new ui.ResponsiveUIHelper(this.el, this.onSizeChange);
    this.size = ui.ResponsiveUIHelper.getSize(this.el.parentElement.clientWidth);
  }
  async componentDidLoad() {
    const { viewedUserId, calendarConfigId } = this;
    const { context, headers } = session.getSessionDetails();
    const mentornityApi = session.createMentornityApiInstance(session.mentornityApiEndpoint, headers);
    mentornityApi.getOrganisationConfig(context.organisationId)
      .then((response) => {
      this.organisationConfig = session.Config.decode(response);
    });
    this.meetingGoalConfig = await mentornityApi.getOrganisationMeetingGoalConfig(context.organisationDomain);
    const calendarConfig = await this.apiTakvim.getCalendarConfig(calendarConfigId).catch(e => {
      this.error = e;
    });
    if (!calendarConfig)
      return;
    this.calendarConfig = calendarConfig;
    // get all data configs that are used in the calendar config
    // this is needed to query the guests and properly display them in the guest selection
    const promises = [];
    calendarConfig.guestDefinitions.forEach(guestDefinition => {
      promises.push(this.apiData.get('data-configs', guestDefinition.tableId, { fields: new dataTransferField.DataTransferField('fields') }));
      if (guestDefinition.membershipFieldIdInTable) {
        promises.push(this.apiData.get('data-configs', guestDefinition.membershipFieldIdInTable, { fields: new dataTransferField.DataTransferField('fields') }));
      }
    });
    const dataConfigs = await Promise.all(promises);
    if (!dataConfigs)
      return;
    this.dataConfigs = dataConfigs;
    const availabilities = await this.apiTakvim.getAvailabilitiesOfUser(viewedUserId).catch(e => {
      this.error = e;
    }).finally(() => this.isProgressing = false);
    if (!availabilities)
      return;
    this.availabilities = availabilities.results;
    // get the earliest start time and latest end time of the availabilities to fetch the unavailabilities for that time period
    const { startDate, endDate } = getTimeFrameOfAvailabilities(availabilities.results);
    if (startDate && endDate) {
      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.generatedAvailabilities = generateAvailabilities(availabilities.results, unavailabilitiesOfOtherUser.results);
    }
    else {
      this.generatedAvailabilities = generateAvailabilities(availabilities.results, []);
    }
    if (!this.isMobileUI()) {
      // invoke onSelectDate for generating initial slots
      if (this.generatedAvailabilities.length > 0) {
        // focus on the date with the first availability
        this.selectedDate = new Date(this.generatedAvailabilities[0].startDate);
      }
      else {
        // focus on today
        this.selectedDate = new Date();
      }
    }
  }
  render() {
    const { calendarConfigId, calendarConfig, generatedAvailabilities, selectedDate, selectedTime, strings, userId, membershipConfigId, viewedUserId, viewedUserMembershipConfigId, weekStartDay, } = this;
    if (!calendarConfig) {
      return null;
    }
    const showMeetingDetailsForm = !!selectedDate && !!selectedTime;
    const { fields: meetingDetailsFormFields } = this.formFields();
    const userMeetingWith = this.guests[1];
    const dialogTitle = index$3.SozlukApi.build(strings.meetingWith, {
      fullName: userMeetingWith.firstName + ' ' + userMeetingWith.lastName
    });
    if (this.isMobileUI()) {
      return (index.h(index.Host, { class: "d-flex mobile" }, index.h("dvn-card", { class: "date-picker-container", bodyLeaned: true, leaned: true, elevation: 0, width: "100%" }, index.h("div", { class: "d-flex justify-content-center" }, index.h("dvn-date-picker", { embedded: true, leaned: true, value: generatedAvailabilities === null || generatedAvailabilities === void 0 ? void 0 : generatedAvailabilities.map(ca => new Date(ca.startDate)), onChange: (e) => this.selectedDate = e.detail, strings: strings, weekStartDay: weekStartDay }))), index.h("dvn-dialog", { class: "confirmation-dialog", shown: !!selectedDate || showMeetingDetailsForm, onDismiss: (e) => {
          e.preventDefault();
          e.stopImmediatePropagation();
          this.createMeetingError = undefined;
          this.selectedAvailability = undefined;
          if (selectedTime) {
            this.selectedTime = undefined;
          }
          else {
            this.selectedDate = undefined;
          }
        }, raw: !!selectedDate && !showMeetingDetailsForm }, (selectedDate && !showMeetingDetailsForm) &&
        index.h("takvim-available-time-picker-selected-day", { availabilities: this.generatedAvailabilities, calenderConfig: calendarConfig, selectedDate: selectedDate, userId: userId, membershipConfigId: membershipConfigId, userSettings: this.userSettings, viewedUserId: viewedUserId, viewedUserMembershipConfigId: viewedUserMembershipConfigId, calendarConfigId: calendarConfigId, apiTakvim: this.apiTakvim, onSelectTime: this.onSelectTime, strings: strings }), showMeetingDetailsForm &&
        this.displayMeetingDetails(meetingDetailsFormFields, dialogTitle))));
    }
    return (index.h(index.Host, { class: "d-flex desktop" }, index.h("dvn-date-picker", { embedded: true, leaned: true, value: generatedAvailabilities === null || generatedAvailabilities === void 0 ? void 0 : generatedAvailabilities.map(ca => new Date(ca.startDate)), highlightedDay: this.selectedDate, onChange: (e) => this.selectedDate = e.detail, strings: strings, weekStartDay: weekStartDay }), index.h("takvim-available-time-picker-selected-day", { availabilities: this.generatedAvailabilities, calenderConfig: calendarConfig, selectedDate: selectedDate, userId: userId, membershipConfigId: membershipConfigId, userSettings: this.userSettings, viewedUserId: viewedUserId, viewedUserMembershipConfigId: viewedUserMembershipConfigId, calendarConfigId: calendarConfigId, apiTakvim: this.apiTakvim, onSelectTime: this.onSelectTime, strings: strings }), index.h("dvn-dialog", { class: "confirmation-dialog", shown: showMeetingDetailsForm, onDismiss: (e) => {
        e.preventDefault();
        e.stopImmediatePropagation();
        this.selectedTime = undefined;
        this.createMeetingError = undefined;
        this.selectedAvailability = undefined;
        this.errorMessage = undefined;
        this.meetingType = undefined;
      }, minHeight: '240px' }, this.displayMeetingDetails(meetingDetailsFormFields, dialogTitle))));
  }
  get el() { return index.getElement(this); }
};
TakvimAvailableTimePicker.style = takvimAvailableTimePickerCss;

const takvimAvailableTimePickerSelectedDayCss = "takvim-available-time-picker-selected-day{-ms-flex:1;flex:1;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}takvim-available-time-picker-selected-day .selected-day-container{-ms-flex:1;flex:1;max-height:calc(var(--date-picker-body-height) + 75px)}@-webkit-keyframes fadeInOpacity{0%{opacity:0;margin-left:10px}100%{opacity:1;margin-left:0}}@keyframes fadeInOpacity{0%{opacity:0;margin-left:10px}100%{opacity:1;margin-left:0}}takvim-available-time-picker-selected-day .selected-day-container .day-title{-webkit-animation-name:fadeInOpacity;animation-name:fadeInOpacity;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-duration:0.3s;animation-duration:0.3s}takvim-available-time-picker-selected-day .selected-day-container .progress-container{display:-ms-flexbox;display:flex;height:100%;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;padding-bottom:1rem}takvim-available-time-picker-selected-day .selected-day-container .selected-day-availabilities dvn-card{margin:0 0 0.5rem 0;text-align:center;font-size:0.9em}takvim-available-time-picker-selected-day .selected-day-container .no-availability-message{font-size:0.9em}takvim-available-time-picker-selected-day .selected-day-container .custom-time-picker{height:100%;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}takvim-available-time-picker-selected-day .selected-day-container .custom-time-picker table{-ms-flex:1;flex:1}";

const conflictSourceNames = {
  'google-calendar': 'Google Calendar',
  'microsoft-calendar': 'Microsoft Calendar',
  'mentornity-calendar': 'calendar',
};
const TakvimAvailableTimePickerSelectedDay = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.selectTime = index.createEvent(this, "selectTime", 7);
    /**
     * 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 = i18n.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 = index$4.momentTimezone.tz(timeString, 'D/M/YYYY h:mm', timeZone).toDate();
      const endHour = dateUtils.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 => dateUtils.isSameDay(new Date(ca.startDate), selectedDate))
      // sort to show slots in order if there are multiple availabilities with the same duration
      .sort((a, b) => (dateUtils.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 = '';
    timeZones.zoneConfig.forEach(group => {
      group.zones.forEach(zone => {
        if (timeZone === zone.value) {
          zoneName = `${zone.name} (${calendar.CalendarUtils.getZoneAbbr(zone.value)})`;
          // zoneName = zone.name;
        }
      });
    });
    let cardHeader = `${calendar.CalendarUtils.format(selectedDate, 'DD MMMM YYYY')}`;
    if (dateFormat === "MM/DD/YYYY") {
      cardHeader = `${calendar.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 (index.h(index.Host, null, index.h("dvn-card", { extraClass: "selected-day-container", elevation: 0, leaned: true }, index.h("dvn-card-header", { title: title, slot: "header", separated: false }), index.h("div", { class: "progress-container" }, index.h("dvn-progress", { indefinite: true, tint: "primary" })))));
    }
    return (index.h(index.Host, null, index.h("dvn-card", { extraClass: "selected-day-container", elevation: 0, leaned: true }, index.h("div", { slot: "header", class: "available-time-picker-date-header p-3 d-flex justify-content-between align-content-center" }, index.h("h4", { key: cardHeader, class: "mt-0 mb-0 day-title" }, cardHeader), index.h("span", { class: "text-neutral" }, index.h("i", { class: 'uil uil-clock' }), zoneName)), isProgressing &&
      index.h("div", { class: "progress-container" }, index.h("dvn-progress", { indefinite: true, tint: "primary" })), index.h("div", { class: "custom-time-picker", style: { display: isPickingCustomTime ? 'flex' : 'none' } }, index.h("table", null, index.h("tbody", null, index.h("tr", null, index.h("td", null, strings.time), index.h("td", null, index.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 }))), index.h("tr", null, index.h("td", null, strings.duration), index.h("td", null, index.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 => (index.h("dvn-select-option", { value: `${minute}` }, `${minute} ${strings.min}`)))))))), index.h("div", { class: "d-flex justify-content-end mt-2" }, index.h("dvn-button", { tint: "primary", onClick: this.onSelectCustomTime }, strings.done), index.h("dvn-button", { tint: "neutral", onClick: () => this.isPickingCustomTime = false }, strings.cancel))), index.h("div", { class: "selected-day-availabilities", style: { display: isPickingCustomTime ? 'none' : 'block' } }, isPickingOneOfAvailabilitiesOfTheSelectedDate &&
      index.h("div", { class: "duration-options-container" }, durationForTheSelectedDate.map(duration => (index.h("dvn-card", { elevation: 0, outlined: true, selectable: true, onClick: () => this.onSelectDuration(duration) }, index$3.SozlukApi.build(strings.bookWithDuration, { duration }))))), isPickingTimeSlot &&
      index.h("div", { class: "slots-container" }, timeSlots.map(slot => (index.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 }, calendar.CalendarUtils.format(slot.start, 'HH:mm'), " - ", calendar.CalendarUtils.format(slot.end, 'HH:mm'), slot.sessionUserConflict &&
        index.h("div", { class: "session-user-conflict-message mt-1" }, index.h("small", null, index$3.SozlukApi.build(strings.conflictsWithCalendar, {
          meetingName: slot.sessionUserConflict.name,
          calendarName: conflictSourceNames[slot.sessionUserConflict.source] || '',
        }))))))), (!isPickingOneOfAvailabilitiesOfTheSelectedDate && !isProgressing) &&
      (calendarPermissions.canPickCustomTime
        ? index.h("dvn-card", { extraClass: "pick-custom-time-button", elevation: 0, outlined: true, selectable: true, onClick: () => this.isPickingCustomTime = true }, strings.pickCustomTime)
        : (timeSlots.length === 0 && index.h("div", { class: "no-availability-message text-centered mt-3" }, availabilitiesForTheSelectedDate.length
          ? strings.noAvailabilityLeftForDay
          : strings.noAvailabilityForDay)))))));
  }
  static get watchers() { return {
    "selectedDate": ["onSelectedDateChange"]
  }; }
};
TakvimAvailableTimePickerSelectedDay.style = takvimAvailableTimePickerSelectedDayCss;

exports.takvim_available_time_picker = TakvimAvailableTimePicker;
exports.takvim_available_time_picker_selected_day = TakvimAvailableTimePickerSelectedDay;
