import { State } from "./../index";
import { ActionContext, Module } from "vuex";
import { CalendarRemote } from "../../../../types";
import { fetchCalendarRemoteForUser } from "../../../Calendar/api";
import { EventInput } from "@fullcalendar/core";
import { remoteToFullCalendarEvent } from "../../../Calendar/store/utils";
import { TransportExceptionInterface } from "../../../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods";
import { COLORS } from "../../../Calendar/const";

export interface CalendarRemotesState {
  remotes: EventInput[];
  remotesLoaded: { start: number; end: number }[];
  remotesIndex: Set<string>;
  key: number;
}

type Context = ActionContext<CalendarRemotesState, State>;

export default {
  namespaced: true,
  state: (): CalendarRemotesState => ({
    remotes: [],
    remotesLoaded: [],
    remotesIndex: new Set<string>(),
    key: 0,
  }),
  getters: {
    isRemotesLoaded:
      (state: CalendarRemotesState) =>
      ({ start, end }: { start: Date; end: Date }): boolean => {
        for (const range of state.remotesLoaded) {
          if (start.getTime() === range.start && end.getTime() === range.end) {
            return true;
          }
        }

        return false;
      },
  },
  mutations: {
    addRemotes(state: CalendarRemotesState, ranges: CalendarRemote[]) {
      console.log("addRemotes", ranges);

      const toAdd = ranges
        .map((cr) => remoteToFullCalendarEvent(cr))
        .filter((r) => !state.remotesIndex.has(r.id));

      toAdd.forEach((r) => {
        state.remotesIndex.add(r.id);
        state.remotes.push(r);
      });
      state.key = state.key + toAdd.length;
    },
    addLoaded(
      state: CalendarRemotesState,
      payload: { start: Date; end: Date },
    ) {
      state.remotesLoaded.push({
        start: payload.start.getTime(),
        end: payload.end.getTime(),
      });
    },
  },
  actions: {
    fetchRemotes(
      ctx: Context,
      payload: { start: Date; end: Date },
    ): Promise<null> {
      const start = payload.start;
      const end = payload.end;

      if (ctx.rootGetters["me/getMe"] === null) {
        return Promise.resolve(null);
      }

      if (ctx.getters.isRemotesLoaded({ start, end })) {
        return Promise.resolve(ctx.getters.getRangeSource);
      }

      ctx.commit("addLoaded", {
        start: start,
        end: end,
      });

      return fetchCalendarRemoteForUser(ctx.rootGetters["me/getMe"], start, end)
        .then((remotes: CalendarRemote[]) => {
          // to be add when reactivity problem will be solve ?
          //ctx.commit('addRemotes', remotes);
          const inputs = remotes
            .map((cr) => remoteToFullCalendarEvent(cr))
            .map((cr) => ({
              ...cr,
              backgroundColor: COLORS[0],
              textColor: "black",
              editable: false,
            }));
          ctx.commit("calendarRanges/addExternals", inputs, {
            root: true,
          });
          return Promise.resolve(null);
        })
        .catch((e: TransportExceptionInterface) => {
          console.error(e);

          return Promise.resolve(null);
        });
    },
  },
} as Module<CalendarRemotesState, State>;
