const defaultConfig = {
  cycleDuration: 4000,
  delay: 5000,
};

interface LoaderConfig {
  cycleDuration?: number;
  delay?: number;
}

export default class Loader {
  element: HTMLElement;
  config: LoaderConfig;
  interval: number | null;
  delay: number | null;
  currentMessageIndex: number;
  messages: string[];

  constructor(element: HTMLElement, config?: LoaderConfig) {
    this.element = element;
    this.config = { ...defaultConfig, ...config };

    this.interval = null;
    this.delay = null;
    this.currentMessageIndex = 0;
    this.messages = [];
    this.cycleMessages = this.cycleMessages.bind(this);

    (this.element as any).ODS_Loader = this;

    this.init();
  }

  initBody() {
    const messagesAttr = this.element.getAttribute("data-loader-messages");
    this.messages = messagesAttr ? JSON.parse(messagesAttr) : [];

    if (this.messages.length) {
      this.interval = window.setInterval(
        this.cycleMessages,
        this.config.cycleDuration ?? defaultConfig.cycleDuration,
      );
    }
  }

  init() {
    if (this.element.hasAttribute("data-loader-delayed")) {
      this.delay = window.setTimeout(() => {
        if (
          this.element.parentNode &&
          this.element.parentNode instanceof HTMLElement
        ) {
          this.element.parentNode.classList.remove("hide");
        }
        this.initBody();
      }, this.config.delay ?? defaultConfig.delay);
    } else {
      this.initBody();
    }
  }

  destroy() {
    if (this.interval) {
      window.clearInterval(this.interval);
    }
    if (this.delay) {
      window.clearTimeout(this.delay);
    }
  }

  cycleMessages() {
    if (this.currentMessageIndex < this.messages.length) {
      this.element.innerText = this.messages[this.currentMessageIndex];
      this.currentMessageIndex += 1;
    } else {
      this.destroy();
    }
  }

  static getInstance(el: HTMLElement): Loader | null {
    return el && (el as any).ODS_Loader
      ? ((el as any).ODS_Loader as Loader)
      : null;
  }
}
