'use strict';

const index = require('./index-5dc304ef.js');

/* eslint-disable no-underscore-dangle */
function comparator(a, b) {
  if (a.startDate < b.startDate)
    return -1;
  else if (a.startDate > b.startDate)
    return 1;
  return 0;
}
function generateSlots(availableTime) {
  const slots = [];
  const blockedSlots = availableTime.blockedSlots || [];
  const availableTimeDuration = availableTime.endDate - availableTime.startDate;
  const millisecondsPerMeeting = availableTime.meetingDuration * 60;
  const millisecondsPerBreak = availableTime.meetingBreaks
    ? availableTime.meetingBreaks * 60 : 0;
  const slotCount = availableTimeDuration / millisecondsPerMeeting;
  for (let si = 0; si < slotCount; si += 1) {
    const startDate = availableTime.startDate
      + (si * (millisecondsPerMeeting + millisecondsPerBreak));
    const endDate = startDate + millisecondsPerMeeting;
    const timeSlot = {
      endDate,
      startDate: startDate + 1,
      location: availableTime.location,
      duration: availableTime.meetingDuration,
      isBlocked: blockedSlots.indexOf(si) > -1,
    };
    slots.push(timeSlot);
  }
  return slots;
}
const CalendarUtils = {
  // default timezone is İstanbul
  timeZone: 'Europe/Istanbul',
  // default language is English
  locale: 'tr',
  setLocale(locale) {
    index.momentTimezone.locale(locale);
    CalendarUtils.locale = locale;
  },
  setTimeZone(timeZone) {
    // hack for Turkey time zone problem
    if (timeZone === 'Europe/Istanbul') {
      CalendarUtils.timeZone = 'Europe/Moscow';
    }
    else {
      CalendarUtils.timeZone = timeZone;
    }
  },
  setTimeFormat(timeFormat) {
    CalendarUtils.timeFormat = timeFormat;
  },
  fixHourDifference(date) {
    const browserOffset = new Date().getTimezoneOffset();
    const timeZoneOffset = index.momentTimezone.tz.zone(CalendarUtils.timeZone).offset(new Date());
    const diff = (browserOffset - timeZoneOffset) / 60;
    date.setHours(date.getHours() - diff);
    return date;
  },
  format(date, formatString) {
    if (formatString === 'HH:mm' && CalendarUtils.timeFormat === '12-hour') {
      return index.momentTimezone(date).tz(CalendarUtils.timeZone).format('hh:mm A');
    }
    return index.momentTimezone(date).tz(CalendarUtils.timeZone).format(formatString);
  },
  /**
   * Return startDate and endDate Unix time stamp values from the date objects in parameters.
   *
   * @param date (JS date object) of the selected day.
   * @param startTime (JS date object) of the start hour.
   * @param endTime (JS date object) of the end hour.
   * @returns {{startDate: number, endDate: number}}
   */
  getStartAndEndDateFromInputs(date, startTime, endTime) {
    let startDate = new Date(date.getTime());
    startDate.setHours(startTime.getHours(), startTime.getMinutes(), 0);
    let endDate = new Date(date.getTime());
    endDate.setHours(endTime.getHours(), endTime.getMinutes(), 0);
    startDate = CalendarUtils.fixHourDifference(startDate);
    endDate = CalendarUtils.fixHourDifference(endDate);
    // convert dates to unix time
    return {
      startDate: startDate.getTime() / 1000,
      endDate: endDate.getTime() / 1000,
    };
  },
  elapsedTime(date) {
    return index.momentTimezone(date).tz(CalendarUtils.timeZone).fromNow();
  },
  elapsedTimeBetweenDates(date1, date2) {
    return index.momentTimezone(date1).from(index.momentTimezone(date2));
  },
  getMonday() {
    return index.momentTimezone().startOf('isoweek');
  },
  getStartEndOfWeek(relativeWeekNumber = 0) {
    // const relativeDate = new Date();
    // relativeDate.setDate(relativeDate.getDate() + (relativeWeekNumber * 7));
    const addition = relativeWeekNumber * (7 * 24 * 60 * 60 * 1000);
    const monday = new Date(new Date(CalendarUtils.getMonday()).getTime() + addition);
    monday.setHours(0, 0, 0, 0);
    const sunday = new Date(monday.getTime());
    sunday.setDate(monday.getDate() + 6);
    sunday.setHours(23, 59, 59, 99);
    return { relativeWeekNumber, firstDayOfWeek: monday, lastDayOfWeek: sunday };
  },
  getCalendarDataWithBundle(events, availabilities = [], dayLimit = 7, firstDayOfWeek = CalendarUtils.getStartEndOfWeek().firstDayOfWeek) {
    const headerDayInfo = [];
    const eventAndSlotInfoForWeek = [];
    events.sort(comparator);
    availabilities.sort(comparator);
    for (let i = 0; i < dayLimit; i += 1) {
      const eventAndSlotInfoForDay = {
        dayData: {
          availabilities: [],
          isEmpty: true,
        },
        eventList: [],
      };
      const day = new Date(firstDayOfWeek);
      day.setDate(day.getDate() + i);
      let eventIndex = 0;
      for (let ati = 0; ati < availabilities.length; ati += 1) {
        const availableTime = availabilities[ati];
        const availableTimeDate = new Date(availableTime.startDate * 1000);
        const blockedSlots = availableTime.blockedSlots || [];
        const timeSlots = [...(availableTime.slots || generateSlots(availableTime))];
        for (let j = 0; j < timeSlots.length; j += 1) {
          timeSlots[j].isBlocked = blockedSlots.indexOf(j) > -1;
        }
        if (day.toDateString() === availableTimeDate.toDateString()) {
          let shouldContinue = availableTime && events && events.length > eventIndex;
          const eventsInThisAvailability = [];
          while (shouldContinue) {
            const event = events[eventIndex];
            if (!event) {
              break;
            }
            if (availableTime.startDate <= event.startDate
              && availableTime.endDate >= event.endDate) {
              eventsInThisAvailability.push(event);
              eventIndex += 1;
              shouldContinue = events.length > eventIndex;
            }
            else if (availableTime.startDate > event.startDate) {
              eventIndex += 1;
            }
            else {
              shouldContinue = false;
            }
          }
          const info = {
            timeSlots,
            availability: availableTime,
            eventList: eventsInThisAvailability,
          };
          eventAndSlotInfoForDay.dayData.availabilities.push(info);
          eventAndSlotInfoForDay.dayData.isEmpty = false;
        }
      }
      const isDayEmpty = eventAndSlotInfoForDay.dayData.isEmpty;
      if (!isDayEmpty) {
        eventAndSlotInfoForWeek.push(eventAndSlotInfoForDay);
        headerDayInfo.push({
          dayNumber: index.momentTimezone(day).format('D'),
          dayNameShort: index.momentTimezone(day).format('ddd'),
          dayName: index.momentTimezone(day).format('dddd'),
          monthName: index.momentTimezone(day).format('MMM'),
        });
      }
    }
    return {
      headerDayInfo,
      eventAndSlotInfoForWeek,
    };
  },
  orderEventsAndAvailabilities(availableTimeSlots, eventList) {
    let listToShow = [];
    // MongoDB doesn't sort the events in the same day correctly.
    // sort them manually for now. but FIX IT later
    eventList.sort(comparator);
    if (availableTimeSlots.length === 0) {
      listToShow = eventList;
    }
    else if (eventList.length === 0) {
      listToShow = availableTimeSlots;
    }
    else {
      let slotIndex = 0;
      let eventIndex = 0;
      let lastAddedItemEndTime = 0;
      const hasNext = true;
      while (hasNext) {
        const slot = slotIndex < availableTimeSlots.length ? availableTimeSlots[slotIndex] : null;
        const event = eventIndex < eventList.length ? eventList[eventIndex] : null;
        if (!event && !slot) {
          break;
        }
        else if (!slot && event) {
          eventIndex += 1;
          if (event.startDate >= lastAddedItemEndTime) {
            listToShow.push(event);
            lastAddedItemEndTime = event.endDate;
          }
        }
        else if (!event && slot) {
          slotIndex += 1;
          if (slot.startDate >= lastAddedItemEndTime) {
            listToShow.push(slot);
            lastAddedItemEndTime = slot.endDate;
          }
        }
        else if (event.startDate <= slot.startDate) {
          eventIndex += 1;
          if (event.startDate >= lastAddedItemEndTime) {
            listToShow.push(event);
            lastAddedItemEndTime = event.endDate;
          }
        }
        else {
          slotIndex += 1;
          if (slot.startDate >= lastAddedItemEndTime) {
            listToShow.push(slot);
            lastAddedItemEndTime = slot.endDate;
          }
        }
      }
    }
    return listToShow;
  },
  getMeetingGoalTitle(context, event) {
    const hasMeetingGoalConfig = context.meetingGoalConfig
      && context.meetingGoalConfig.meetingGoals
      && context.meetingGoalConfig.meetingGoals.length > 0;
    if (hasMeetingGoalConfig) {
      for (let i = 0; i < context.meetingGoalConfig.meetingGoals.length; i += 1) {
        const goal = context.meetingGoalConfig.meetingGoals[i];
        if (goal.identifier === event.meetingGoalIdentifier) {
          return goal.meetingTitle;
        }
      }
    }
    return undefined;
  },
  getMeetingGoalOfEvent(context, event) {
    const hasMeetingGoalConfig = context.meetingGoalConfig
      && context.meetingGoalConfig.meetingGoals
      && context.meetingGoalConfig.meetingGoals.length > 0;
    if (hasMeetingGoalConfig) {
      for (let i = 0; i < context.meetingGoalConfig.meetingGoals.length; i += 1) {
        const goal = context.meetingGoalConfig.meetingGoals[i];
        if (goal.identifier === event.meetingGoalIdentifier) {
          return goal;
        }
      }
    }
    return undefined;
  },
  getRelationsOfUserForMeeting(context, event, account) {
    const guests = [...event.guests];
    const mentor = guests.splice(0, 1)[0];
    const mentees = guests;
    const isParticipantAsMentor = mentor._id === account._id;
    let isParticipantAsGroupMember = false;
    let isParticipantAsMentee = false;
    if (account) {
      for (let i = 0; i < mentees.length; i += 1) {
        if (mentees[i]._id === account._id) {
          isParticipantAsMentee = true;
          break;
        }
        else if (context.group && mentees[i]._id === context.group._id) {
          isParticipantAsGroupMember = true;
          break;
        }
      }
    }
    return {
      isParticipantAsMentor,
      isParticipantAsMentee,
      isParticipantAsGroupMember,
    };
  },
  getMeetingGoalForms(context, userType, event) {
    const meetingGoal = CalendarUtils.getMeetingGoalOfEvent(context, event);
    if (!meetingGoal) {
      return {};
    }
    let meetingGoalSpecifications;
    if (userType === 'mentor') {
      meetingGoalSpecifications = meetingGoal.specifications.mentor;
    }
    else if (userType === 'mentee') {
      meetingGoalSpecifications = meetingGoal.specifications.mentee;
    }
    const hasPreMeetingQuestions = meetingGoalSpecifications
      && meetingGoalSpecifications.preMeetingForm
      && meetingGoalSpecifications.preMeetingForm.fields
      && meetingGoalSpecifications.preMeetingForm.fields.length > 0;
    const hasPostMeetingQuestions = meetingGoalSpecifications
      && meetingGoalSpecifications.postMeetingForm
      && meetingGoalSpecifications.postMeetingForm.fields
      && meetingGoalSpecifications.postMeetingForm.fields.length > 0;
    return {
      description: meetingGoalSpecifications.description,
      preMeetingForm: hasPreMeetingQuestions && meetingGoalSpecifications.preMeetingForm,
      postMeetingForm: hasPostMeetingQuestions && meetingGoalSpecifications.postMeetingForm,
    };
  },
};

exports.CalendarUtils = CalendarUtils;
