import { ResponsiveSize, ResponsiveUIHelper } from '@dvn/alaca/utils/ui';
import { SingleChoiceField, SingleChoiceFieldOption } from '@dvn/core/doldurma/src/fields/single-choice';
import { TextField } from '@dvn/core/doldurma/src/fields/text';
import { ConcealerConditional, Equal } from '@dvn/core/doldurma/src/interceptors/concealers/ConcealerGenericRule';
import { capitalize } from '@dvn/core/util/string';
import { User } from '@dvn/kimlik/api/models';
import { generateAvailabilities } from '@dvn/takvim/components/utils';
import { Component, Element, Event, h, Host, Prop, State } from '@stencil/core';
import moment from 'moment-timezone';
const meetingLocationTypes = [
  {
    name: 'Custom',
    value: 'custom',
  },
  {
    name: 'Jitsi Meet',
    value: 'jitsi',
  },
  {
    name: 'Zoom',
    value: 'zoom',
  },
];
const formErrors = (error) => {
  if (!error)
    return [];
  // TODO show proper error messages from i18n
  return [
    capitalize(`${error.data.message.split('-').join(' ')}.`, false),
  ];
};
const formFields = (meetingTypes = [], meetingsByMeetingTypes = {}, isCustom, authPlatforms) => {
  let maxFieldCount = isCustom ? 2 : 0;
  const fields = [];
  const availableMeetingTypes = meetingTypes
    .filter(meetingType => { var _a; return (((_a = meetingsByMeetingTypes[meetingType.id]) === null || _a === void 0 ? void 0 : _a.length) || 0) < meetingType.maxCount; });
  if (meetingTypes && meetingTypes.length > 0) {
    maxFieldCount += 1;
    fields.push(new SingleChoiceField('meetingType', 'Select a Session', availableMeetingTypes.map(meetingType => new SingleChoiceFieldOption(meetingType.name, meetingType.id)), '', 'select').setErrorTitle('Session').require());
  }
  fields.push(...[
    new SingleChoiceField('locationType', 'Location Type', meetingLocationTypes
      // filter out the location types if user doesn't have the corresponding auth platform (zoom)
      .filter(locationType => {
      if (locationType.value === 'custom' || locationType.value === 'jitsi') {
        return true;
      }
      return !!authPlatforms.some(authPlatform => authPlatform.id === locationType.value);
    })
      .map(locationType => new SingleChoiceFieldOption(locationType.name, locationType.value)), '', 'select').setValue('jitsi')
      .setVisibility(isCustom)
      .require(),
    new TextField('location', 'Location', 'Meeting location')
      .addInterceptor('onFormChange', new ConcealerConditional(new Equal('locationType', 'custom')))
      .require()
      .hide()
  ]);
  return { fields, maxFieldCount };
};
export class TakvimAvailableTimePicker {
  constructor() {
    this.meetingsByMeetingTypes = {};
    /**
     * Raw availabilities fetched from the api.
     */
    this.availabilities = [];
    /**
     * Availabilities that are generated by the raw availabilities considering their recurrence.
     * MAX_MONTH_FOR_RECURRENCE is used to limit the availabilities for the future.
     */
    this.generatedAvailabilities = [];
    this.meetingLocationType = 'jitsi';
    this.meetingLocation = '';
    this.isProgressing = true;
    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 < ResponsiveSize.Small;
    this.onSelectTime = async (e) => {
      this.selectedTime = e.detail;
      const showMeetingDetailsForm = !!this.selectedDate && !!this.selectedTime;
      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) => {
      const data = event.detail.values;
      const { location, locationType, meetingType } = data;
      const { startHour, endHour, availabilityId } = this.selectedTime;
      const meeting = {
        locations: [{
            address: location,
            type: locationType,
          }],
        meetingType,
        startDate: startHour.toISOString(),
        endDate: endHour.toISOString(),
        guests: [
          User.generateRef(this.viewedUserId),
          User.generateRef(this.userId),
        ],
        createdBy: 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.selectedDate = new Date(this.selectedDate.toISOString());
      this.createMeeting.emit(Object.assign(Object.assign({}, createMeetingResponse), meeting));
    };
  }
  async componentWillLoad() {
    this.uiHelper = new ResponsiveUIHelper(this.el, this.onSizeChange);
    this.size = ResponsiveUIHelper.getSize(this.el.parentElement.clientWidth);
  }
  async componentDidLoad() {
    const { viewedUserId, calendarConfigId } = this;
    const calenderConfig = await this.apiTakvim.getCalendarConfig(calendarConfigId).catch(e => {
      this.error = e;
    });
    if (!calenderConfig)
      return;
    this.calendarConfig = calenderConfig;
    const availabilities = await this.apiTakvim.getAvailabilitiesOfUser(calendarConfigId, viewedUserId).catch(e => {
      this.error = e;
    }).finally(() => this.isProgressing = false);
    if (!availabilities)
      return;
    this.availabilities = availabilities.results;
    this.generatedAvailabilities = generateAvailabilities(availabilities.results);
    if (!this.isMobileUI()) {
      // invoke onSelectDate for generating slots for today
      this.selectedDate = new Date();
    }
  }
  render() {
    const { calendarConfigId, calendarConfig, createMeetingError, generatedAvailabilities, isProgressing, meetingsByMeetingTypes, meetingTypes, selectedDate, selectedTime, userId, membershipConfigId, viewedUserId, viewedUserMembershipConfigId, } = this;
    const showMeetingDetailsForm = !!selectedDate && !!selectedTime;
    const { fields: meetingDetailsFormFields, maxFieldCount } = formFields(meetingTypes, meetingsByMeetingTypes, !(selectedTime === null || selectedTime === void 0 ? void 0 : selectedTime.availabilityId), this.userSettings.authPlatforms);
    const minFormHeight = `${Math.max(maxFieldCount * 100, (meetingTypes === null || meetingTypes === void 0 ? void 0 : meetingTypes.length) > 0 ? 200 : 120)}px`;
    const timeZone = this.userSettings.timeZone;
    const dialogTitle = `${moment(selectedDate).tz(timeZone).format('DD MMMM')}, ${moment(selectedTime === null || selectedTime === void 0 ? void 0 : selectedTime.startHour).tz(timeZone).format('HH:mm')} - ${moment(selectedTime === null || selectedTime === void 0 ? void 0 : selectedTime.endHour).tz(timeZone).format('HH:mm')}`;
    if (this.isMobileUI()) {
      return (h(Host, { class: "d-flex mobile" },
        h("dvn-card", { class: "date-picker-container", bodyLeaned: true, leaned: true, elevation: 0, width: "100%" },
          h("div", { class: "d-flex justify-content-center" },
            h("dvn-date-picker", { embedded: true, leaned: true, value: generatedAvailabilities.map(ca => new Date(ca.startDate)), onChange: (e) => this.selectedDate = e.detail }))),
        h("dvn-dialog", { class: "confirmation-dialog", shown: !!selectedDate || showMeetingDetailsForm, onDismiss: (e) => {
            e.preventDefault();
            e.stopPropagation();
            this.createMeetingError = undefined;
            if (selectedTime) {
              this.selectedTime = undefined;
            }
            else {
              this.selectedDate = undefined;
            }
          }, raw: !!selectedDate && !showMeetingDetailsForm, title: dialogTitle },
          (selectedDate && !showMeetingDetailsForm) &&
            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 }),
          showMeetingDetailsForm &&
            h("div", { class: "ml-3 mr-3 mt-3 mb-2" },
              h("div", null,
                "Are you sure to schedule this meeting?",
                h("br", null),
                h("br", null)),
              h("doldurma-form", { key: `${selectedTime === null || selectedTime === void 0 ? void 0 : selectedTime.startHour}-${selectedTime === null || selectedTime === void 0 ? void 0 : selectedTime.endHour}`, fields: meetingDetailsFormFields, onSubmit: this.onSubmitForm, submitButtonLabel: "Schedule meeting", progressing: isProgressing, formErrors: formErrors(createMeetingError), minHeight: minFormHeight, width: '100%' })))));
    }
    return (h(Host, { class: "d-flex desktop" },
      h("dvn-date-picker", { embedded: true, leaned: true, value: generatedAvailabilities.map(ca => new Date(ca.startDate)), highlightedDay: this.selectedDate, onChange: (e) => this.selectedDate = e.detail }),
      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 }),
      h("dvn-dialog", { class: "confirmation-dialog", shown: showMeetingDetailsForm, onDismiss: () => {
          this.selectedTime = undefined;
          this.createMeetingError = undefined;
        }, minHeight: '240px', title: dialogTitle },
        h("div", null,
          "Are you sure to schedule this meeting?",
          h("br", null),
          h("br", null)),
        h("doldurma-form", { key: `${selectedTime === null || selectedTime === void 0 ? void 0 : selectedTime.startHour}-${selectedTime === null || selectedTime === void 0 ? void 0 : selectedTime.endHour}`, fields: meetingDetailsFormFields, onSubmit: this.onSubmitForm, submitButtonLabel: "Schedule meeting", progressing: isProgressing, formErrors: formErrors(createMeetingError), minHeight: minFormHeight, width: '100%' }))));
  }
  static get is() { return "takvim-available-time-picker"; }
  static get originalStyleUrls() { return {
    "$": ["takvim-available-time-picker.scss"]
  }; }
  static get styleUrls() { return {
    "$": ["takvim-available-time-picker.css"]
  }; }
  static get properties() { return {
    "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
    },
    "meetingTypes": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "MeetingType[]",
        "resolved": "MeetingType[]",
        "references": {
          "MeetingType": {
            "location": "import",
            "path": "@dvn/takvim/models/MeetingType"
          }
        }
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "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": ""
      }
    }
  }; }
  static get states() { return {
    "calendarConfig": {},
    "meetings": {},
    "meetingsByMeetingTypes": {},
    "availabilities": {},
    "generatedAvailabilities": {},
    "selectedDate": {},
    "selectedTime": {},
    "meetingLocationType": {},
    "meetingLocation": {},
    "isProgressing": {},
    "error": {},
    "createMeetingError": {},
    "size": {}
  }; }
  static get events() { return [{
      "method": "createMeeting",
      "name": "createMeeting",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "any",
        "resolved": "any",
        "references": {}
      }
    }]; }
  static get elementRef() { return "el"; }
}
