import { IUser } from "@api-client/core/build/browser.js";
import { AddConfigEnvironmentInit } from "../bindings/base/ConfigurationBindings.js";
import { Events } from "../events/Events.js";
import { ConfigBroadcast, ConfigBroadcastChannel } from "../lib/config/Config.js";

/**
 * A class that caches user info in memory so the application reduces the number
 * of requests to the backend requesting a user info.
 */
class UserCache {
  protected cached = new Map<string, IUser | undefined>();

  /**
   * Application configuration broadcast channel.
   */
  protected configBroadcast = new BroadcastChannel(ConfigBroadcastChannel);

  constructor() {
    this.configBroadcast.addEventListener('message', this.handleConfigBroadcast.bind(this))
  }

  async getUser(key: string): Promise<IUser | undefined> {
    const existing = this.cached.get(key);
    if (existing) {
      return existing;
    }
    const read = await this.requestUser(key);
    this.cached.set(key, read);
    return read;
  }

  protected async requestUser(key: string): Promise<IUser | undefined> {
    try {
      const result = await Events.Store.User.read(key);
      return result;
    } catch (e) {
      // ....
    }
    return undefined;
  }

  protected handleConfigBroadcast(e: MessageEvent): void {
    const event = e.data as ConfigBroadcast;
    const { path } = event;
    if (path === 'environment.setDefault') {
      this.cached = new Map();
    } else if (path === 'environment.add') {
      const init = event.init as AddConfigEnvironmentInit;
      if (init.asDefault) {
        this.cached = new Map();
      }
    }
  }
}

const instance = new UserCache();
export default instance;
