import googleCalendar from "../../google_calendar.app.mjs";
import taskScheduler from "../common/taskScheduler.mjs";
import sampleEmit from "./test-event.mjs";
export default {
  key: "google_calendar-upcoming-event-alert",
  name: "New Upcoming Event Alert",
  description: "Emit new event based on a time interval before an upcoming event in the calendar.",
  version: "0.1.0",
  type: "source",
  props: {
    googleCalendar,
    db: "$.service.db",
    http: "$.interface.http",
    pipedreamApiKey: {
      type: "string",
      label: "Pipedream API Key",
      description: "[Click here to find your Pipedream API key](https://pipedream.com/settings/user)",
      secret: true,
    },
    calendarId: {
      propDefinition: [
        googleCalendar,
        "calendarId",
      ],
    },
    eventTypes: {
      propDefinition: [
        googleCalendar,
        "eventTypes",
      ],
    },
    time: {
      type: "integer",
      label: "Minutes Before",
      description: "Number of minutes to trigger before the start of the calendar event.",
      min: 0,
      reloadProps: true,
    },
  },
  async additionalProps() {
    const props = {};
    if (this.time > 0) {
      props.timer = {
        type: "$.interface.timer",
        description: "Poll the API to schedule alerts for any newly created events",
        default: {
          intervalSeconds: 60 * this.time,
        },
      };
    }
    return props;
  },
  hooks: {
    async deactivate() {
      const ids = this._getScheduledEventIds();
      if (!ids?.length) {
        return;
      }
      for (const id of ids) {
        if (await this.deleteScheduledEvent({
          body: {
            id,
          },
        }, this.pipedreamApiKey)) {
          console.log("Cancelled scheduled event");
        }
      }
      this._setScheduledEventIds();
    },
  },
  methods: {
    ...taskScheduler.methods,
    _getScheduledEventIds() {
      return this.db.get("scheduledEventIds");
    },
    _setScheduledEventIds(ids) {
      this.db.set("scheduledEventIds", ids);
    },
    _getScheduledCalendarEventIds() {
      return this.db.get("scheduledCalendarEventIds");
    },
    _setScheduledCalendarEventIds(ids) {
      this.db.set("scheduledCalendarEventIds", ids);
    },
    _hasDeployed() {
      const result = this.db.get("hasDeployed");
      this.db.set("hasDeployed", true);
      return result;
    },
    subtractMinutes(date, minutes) {
      return date.getTime() - minutes * 60000;
    },
    async getCalendarEvents() {
      const calendarEvents = [];
      const params = {
        returnOnlyData: false,
        calendarId: this.calendarId,
        eventTypes: this.eventTypes,
      };
      do {
        const {
          data: {
            items, nextPageToken,
          },
        } = await this.googleCalendar.listEvents(params);
        if (items?.length) {
          calendarEvents.push(...items);
        }
        params.pageToken = nextPageToken;
      } while (params.pageToken);
      return calendarEvents;
    },
  },
  async run(event) {
    
    if (!this._hasDeployed()) {
      await this.selfSubscribe(this.pipedreamApiKey);
    }
    const scheduledEventIds = this._getScheduledEventIds() || [];
    
    if (event.$channel === this.selfChannel()) {
      const remainingScheduledEventIds = scheduledEventIds.filter((id) => id !== event["$id"]);
      this._setScheduledEventIds(remainingScheduledEventIds);
      this.emitEvent(event, `Upcoming ${event.summary
        ? event.summary + " "
        : ""}event`);
      return;
    }
    
    const scheduledCalendarEventIds = this._getScheduledCalendarEventIds() || {};
    const calendarEvents = await this.getCalendarEvents();
    for (const calendarEvent of calendarEvents) {
      const startTime = calendarEvent.start
        ? (new Date(calendarEvent.start.dateTime || calendarEvent.start.date))
        : null;
      if (!startTime
        || startTime.getTime() < Date.now()
        || scheduledCalendarEventIds[calendarEvent.id])
      {
        continue;
      }
      const later = new Date(this.subtractMinutes(startTime, this.time));
      const scheduledEventId = this.emitScheduleEvent(calendarEvent, later);
      scheduledEventIds.push(scheduledEventId);
      scheduledCalendarEventIds[calendarEvent.id] = true;
    }
    this._setScheduledEventIds(scheduledEventIds);
    this._setScheduledCalendarEventIds(scheduledCalendarEventIds);
  },
  sampleEmit,
};