type ThemeTypeInternal = 'light' | 'dark'
export type ThemeType = 'default' | ThemeTypeInternal

export class ThemeManager {
  /**
   * Detected system theme.
   */
  #systemTheme: ThemeTypeInternal = 'light'

  /**
   * The theme to use as selected by the user.
   * Default to system default.
   */
  #userTheme: ThemeType = 'default'

  constructor() {
    this.#initMediaQueries()
    // this will use the system-default theme until config is read.
    this.#themeActiveCallback()
  }

  setUserTheme(theme: ThemeType): void {
    this.#userTheme = theme
    this.#themeActiveCallback()
  }

  /**
   * Initializes media queries and observers.
   */
  #initMediaQueries(): void {
    const dark = window.matchMedia('(prefers-color-scheme: dark)')
    if (dark.matches) {
      this.#systemTheme = 'dark'
    }
    dark.addEventListener('change', (e) => {
      this.#systemTheme = e.matches ? 'dark' : 'light'
      this.#themeActiveCallback()
    })
  }

  #themeActiveCallback(): void {
    let theme: ThemeTypeInternal
    if (this.#userTheme === 'default') {
      theme = this.#systemTheme
    } else {
      theme = this.#userTheme
    }
    this.activateTheme(theme)
  }

  activateTheme(type: ThemeTypeInternal): void {
    const root = document.querySelector('html')
    if (!root) {
      return
    }
    const { classList } = root
    // clear all themes
    classList.forEach((value) => {
      if (value.startsWith('theme-')) {
        classList.remove(value)
      }
    })
    const name = `theme-${type}`
    classList.add(name)
  }
}
