
/** Fetch events from server
 */
async function refreshEvents ({commit, dispatch, state, rootState}, [modifiedAfter] = []) {

  if (!modifiedAfter) {
    modifiedAfter = state.timestamp;
  }

  if (state.loading) {
    commit('abortEventsLoading');
  }

  commit('setEventsLoading');
  const pid = rootState.project.projectId;
  const url = modifiedAfter
    ? `/project/${pid}/event/changes/${(new Date(modifiedAfter)).toISOString()}?unique=t`
    : `/project/${pid}/event`;
  const init = {
    cache: "reload",
    signal: state.loading.signal
  };
  const res = await dispatch('api', [url, init]);

  if (res) {
    if (modifiedAfter) {
      commit('setModifiedEvents', res);
    } else {
      commit('setEvents', res);
    }
    commit('setEventsTimestamp');
  }
  commit('clearEventsLoading');

}

/** Return a subset of events from state.events
 */
async function getEvents ({commit, dispatch, state}, [projectId, {sequence, date0, date1, sortBy, sortDesc, itemsPerPage, page, text, label, excludeLabels}]) {
  let filteredEvents = [...state.events];

  if (sortBy) {

    sortBy.forEach( (key, idx) => {
      filteredEvents.sort( (el0, el1) => {
        const a = el0?.[key];
        const b = el1?.[key];
        if (a < b) {
          return -1;
        } else if (a > b) {
          return 1;
        } else if (a == b) {
          return 0;
        } else if (a && !b) {
          return 1;
        } else if (!a && b) {
          return -1;
        } else {
          return 0;
        }
      });
      if (sortDesc && sortDesc[idx] === true) {
        filteredEvents.reverse();
      }
    });

  }

  if (sequence) {
    filteredEvents = filteredEvents.filter( event => event.sequence == sequence );
  }

  if (date0 && date1) {
    filteredEvents = filteredEvents.filter( event =>
      event.tstamp.substr(0, 10) >= date0 && event.tstamp.substr(0, 10) <= date1
    );
  } else if (date0) {
    filteredEvents = filteredEvents.filter( event => event.tstamp.substr(0, 10) == date0 );
  }

  if (text) {
    const tstampFilter = (value, search, item) => {
      return textFilter(value, search, item);
    };

    const numberFilter = (value, search, item) => {
      return value == search;
    };

    const textFilter = (value, search, item) => {
      return String(value).toLowerCase().includes(search.toLowerCase());
    };

    const searchFunctions = {
      tstamp: tstampFilter,
      sequence: numberFilter,
      point: numberFilter,
      remarks: textFilter,
      labels: (value, search, item) => value.some(label => textFilter(label, search, item))
    };

    filteredEvents = filteredEvents.filter ( event => {
      for (let key in searchFunctions) {
        const fn = searchFunctions[key];
        if (fn(event[key], text, event)) {
          return true;
        }
      }
      return false;
    });
  }

  if (label) {
    filteredEvents = filteredEvents.filter( event => event.labels?.includes(label) );
  }

  if (excludeLabels) {
    filteredEvents = filteredEvents.filter( event => !excludeLabels?.some( label => event.labels?.includes(label) ) );
  }

  const count = filteredEvents.length;

  if (itemsPerPage && itemsPerPage > 0) {
    const offset = (page > 0)
      ? (page-1) * itemsPerPage
      : 0;

    filteredEvents = filteredEvents.slice(offset, offset+itemsPerPage);
  }

  return {events: filteredEvents, count};
}

export default { refreshEvents, getEvents };
