export default {
  /**
   * get the main user of the event/Calendar
   *
   * @param state
   * @returns {*|null}
   */
  getMainUser(state) {
    return state.activity.mainUser || null;
  },
  /**
   * return the date of the event/Calendar
   *
   * @param state
   * @returns {Date}
   */
  getEventDate(state) {
    if (null === state.activity.start) {
      return new Date();
    }
    throw "transform date to object ?";
  },
  /**
   * Compute the event sources to show on the FullCalendar
   *
   * @param state
   * @param getters
   * @returns {[]}
   */
  getEventSources(state, getters) {
    let sources = [];

    // current calendar
    if (state.activity.startDate !== null && state.activity.endDate !== null) {
      const s = {
        id: "current",
        events: [
          {
            title: "Rendez-vous",
            start: state.activity.startDate,
            end: state.activity.endDate,
            allDay: false,
            is: "current",
            classNames: ["iscurrent"],
          },
        ],
        editable: state.activity.calendarRange === null,
      };

      sources.push(s);
    }

    for (const [userId, kinds] of state.currentView.users.entries()) {
      if (!state.usersData.has(userId)) {
        console.log("try to get events on a user which not exists", userId);
        continue;
      }

      const userData = state.usersData.get(userId);

      if (kinds.ranges && userData.calendarRanges.length > 0) {
        const s = {
          id: `ranges_${userId}`,
          events: userData.calendarRanges.filter(
            (r) =>
              state.activity.calendarRange === null ||
              r.calendarRangeId !==
                state.activity.calendarRange.calendarRangeId,
          ),
          color: userData.mainColor,
          classNames: ["isrange"],
          backgroundColor: "white",
          textColor: "black",
          editable: false,
        };

        sources.push(s);
      }

      if (kinds.remotes && userData.remotes.length > 0) {
        const s = {
          id: `remote_${userId}`,
          events: userData.remotes,
          color: userData.mainColor,
          textColor: "black",
          editable: false,
        };

        sources.push(s);
      }

      // if remotes is checked, we display also the locals calendars
      if (kinds.remotes && userData.locals.length > 0) {
        const s = {
          id: `local_${userId}`,
          events: userData.locals.filter(
            (l) => l.originId !== state.activity.id,
          ),
          color: userData.mainColor,
          textColor: "black",
          editable: false,
        };

        sources.push(s);
      }
    }

    return sources;
  },
  getInitialDate(state) {
    return state.activity.startDate;
  },
  getInviteForUser: (state) => (user) => {
    return state.activity.invites.find((i) => i.user.id === user.id);
  },
  /**
   * get the user data for a specific user
   *
   * @param state
   * @returns {function(*): unknown}
   */
  getUserData: (state) => (user) => {
    return state.usersData.get(user.id);
  },
  getUserDataById: (state) => (userId) => {
    return state.usersData.get(userId);
  },
  /**
   * return true if the user has an entry in userData
   *
   * @param state
   * @returns {function(*): boolean}
   */
  hasUserData: (state) => (user) => {
    return state.usersData.has(user.id);
  },
  hasUserDataById: (state) => (userId) => {
    return state.usersData.has(userId);
  },
  /**
   * return true if there was a fetch query for event between this date (start and end),
   * those date are included.
   *
   * @param state
   * @param getters
   * @returns {(function({user: *, start: *, end: *}): (boolean))|*}
   */
  isCalendarRangeLoadedForUser:
    (state, getters) =>
    ({ user, start, end }) => {
      if (!getters.hasUserData(user)) {
        return false;
      }

      for (let interval of getters.getUserData(user).calendarRangesLoaded) {
        if (start >= interval.start && end <= interval.end) {
          return true;
        }
      }

      return false;
    },
  /**
   * return true if there was a fetch query for event between this date (start and end),
   * those date are included.
   *
   * @param state
   * @param getters
   * @returns {(function({user: *, start: *, end: *}): (boolean))|*}
   */
  isCalendarRemoteLoadedForUser:
    (state, getters) =>
    ({ user, start, end }) => {
      if (!getters.hasUserData(user)) {
        return false;
      }

      for (let interval of getters.getUserData(user).remotesLoaded) {
        if (start >= interval.start && end <= interval.end) {
          return true;
        }
      }

      return false;
    },
  /**
   * return true if the user ranges are shown on calendar
   *
   * @param state
   * @returns boolean
   */
  isRangeShownOnCalendarForUser: (state) => (user) => {
    const k = state.currentView.users.get(user.id);
    if (typeof k === "undefined") {
      console.error(
        "try to determinate if calendar range is shown and user is not in currentView",
      );
      return false;
    }

    return k.ranges;
  },

  /**
   * return true if the user remote is shown on calendar
   * @param state
   * @returns boolean
   */
  isRemoteShownOnCalendarForUser: (state) => (user) => {
    const k = state.currentView.users.get(user.id);
    if (typeof k === "undefined") {
      console.error(
        "try to determinate if calendar range is shown and user is not in currentView",
      );
      return false;
    }

    return k.remotes;
  },

  getLocationById: (state) => (id) => {
    for (let group of state.availableLocations) {
      console.log("group", group);
      const found = group.locations.find((l) => l.id === id);
      if (typeof found !== "undefined") {
        return found;
      }
    }

    return null;
  },

  suggestedEntities(state, getters) {
    if (typeof state.activity.accompanyingPeriod === "undefined") {
      return [];
    }
    const allEntities = [
      ...getters.suggestedPersons,
      ...getters.suggestedRequestor,
      ...getters.suggestedUser,
      ...getters.suggestedResources,
    ];
    const uniqueIds = [...new Set(allEntities.map((i) => `${i.type}-${i.id}`))];
    return Array.from(
      uniqueIds,
      (id) => allEntities.filter((r) => `${r.type}-${r.id}` === id)[0],
    );
  },
  suggestedPersons(state) {
    const existingPersonIds = state.activity.persons.map((p) => p.id);
    return state.activity.accompanyingPeriod.participations
      .filter((p) => p.endDate === null)
      .map((p) => p.person)
      .filter((p) => !existingPersonIds.includes(p.id));
  },
  suggestedRequestor(state) {
    if (state.activity.accompanyingPeriod.requestor === null) {
      return [];
    }

    const existingPersonIds = state.activity.persons.map((p) => p.id);
    const existingThirdPartyIds = state.activity.thirdParties.map((p) => p.id);
    return [state.activity.accompanyingPeriod.requestor].filter(
      (r) =>
        (r.type === "person" && !existingPersonIds.includes(r.id)) ||
        (r.type === "thirdparty" && !existingThirdPartyIds.includes(r.id)),
    );
  },
  suggestedUser(state) {
    if (null === state.activity.users) {
      return [];
    }
    const existingUserIds = state.activity.users.map((p) => p.id);
    return [state.activity.accompanyingPeriod.user].filter(
      (u) => u !== null && !existingUserIds.includes(u.id),
    );
  },
  suggestedResources(state) {
    const resources = state.activity.accompanyingPeriod.resources;
    const existingPersonIds = state.activity.persons.map((p) => p.id);
    const existingThirdPartyIds = state.activity.thirdParties.map((p) => p.id);
    return state.activity.accompanyingPeriod.resources
      .map((r) => r.resource)
      .filter(
        (r) =>
          (r.type === "person" && !existingPersonIds.includes(r.id)) ||
          (r.type === "thirdparty" && !existingThirdPartyIds.includes(r.id)),
      );
  },
};
