/* eslint-disable @typescript-eslint/no-explicit-any */
import { editor } from 'monaco-editor'

const matcher = window.matchMedia('(prefers-color-scheme: dark)')

function getVariableValue(property: string, defaultValue: string): string {
  const value = getComputedStyle(document.body).getPropertyValue(property).trim()
  if (!value) {
    return defaultValue
  }
  return value
}

/**
 * Creates a base definition of the Monaco theme for the API Client.
 * This is to be used on the monaco instance:
 *
 * ```
 * monaco.editor.defineTheme('HttpTheme', generateMonacoTheme());
 * ```
 */
export function generateMonacoTheme(): editor.IStandaloneThemeData {
  const colorSurface = getVariableValue('--md-sys-color-surface', '#F5F5F5')
  const colorOnSurface = getVariableValue('--md-sys-color-on-surface', '#000000')
  const theme: editor.IStandaloneThemeData = {
    base: matcher.matches ? 'vs-dark' : 'vs',
    inherit: true,
    rules: [
      { background: colorSurface } as editor.ITokenThemeRule,
      // { token: 'other.json', foreground: onSecondaryContainer } as editor.ITokenThemeRule,
    ],
    colors: {
      'editor.background': colorSurface,
      'editor.foreground': colorOnSurface,
    },
  }
  // current-line current-line-margin-both
  // font-family: var(--md-sys-typescale-label-large-font);
  // font-size: var(--md-sys-typescale-label-large-size);
  // letter-spacing: var(--md-sys-typescale-label-large-tracking);
  // line-height: var(--md-sys-typescale-label-large-height);
  // { token: 'comment', foreground: 'ffa500', fontStyle: 'italic underline' },
  return theme
}

/**
 * @param monaco The monaco global object
 * @param config The configuration being passed to the monaco editor instance.
 * @returns The copy of the configuration with `theme` property.
 */
export function assignTheme(
  monaco: any,
  config: editor.IStandaloneEditorConstructionOptions
): editor.IStandaloneEditorConstructionOptions {
  const cnf = { ...config }
  const mdSource = getVariableValue('--md-source', '')
  if (mdSource) {
    ;(monaco.editor as typeof editor).defineTheme('Material', generateMonacoTheme())
    cnf.theme = 'Material'
    return cnf
  }
  if (matcher.matches) {
    cnf.theme = 'vs-dark'
  } else {
    cnf.theme = 'vs'
  }
  return cnf
}

export function setTheme(monaco: any): string {
  const mdSource = getVariableValue('--md-source', '')
  if (mdSource) {
    monaco.editor.defineTheme('Material', generateMonacoTheme())
    return 'Material'
  }
  if (matcher.matches) {
    return 'vs-dark'
  }
  return 'vs'
}

function handleThemeChange(): void {
  // @ts-expect-error Monaco is a global object
  if (!monaco) {
    return
  }
  setTimeout(() => {
    // @ts-expect-error Monaco is a global object
    const name = setTheme(monaco)
    // @ts-expect-error Monaco is a global object
    monaco.editor.setTheme(name)
  }, 100)
}

matcher.addEventListener('change', handleThemeChange)
