import { Injectable, Inject, Renderer2, RendererFactory2, PLATFORM_ID } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { BaseButtonService } from './base-button.service';

@Injectable({
  providedIn: 'root'
})
export class ColorModeService extends BaseButtonService {

  private readonly renderer: Renderer2;

  private themeSubject = new BehaviorSubject<Theme>(GetLocalTheme());
  public themeChanges$ = this.themeSubject.asObservable();

  constructor(@Inject(PLATFORM_ID) private platformId: object, private rendererFactory: RendererFactory2, @Inject(DOCUMENT) public document: Document) {
    super()
    this.renderer = rendererFactory.createRenderer(null, null);
  }

  setTheme(theme: Theme) {
    if (typeof window !== 'undefined')
      localStorage.setItem('theme', theme)
    this.updateTheme();
  }

  updateTheme() {
    let theme: Theme = GetLocalTheme();

    this.themeSubject.next(GetLocalTheme());

    this.themeSubject.next(GetLocalTheme());

    switch(theme) {
      case Theme.Dark: 
      case Theme.Auto:
        this.renderer.addClass(this.document.body, "mat-color-scheme-dark")
        this.renderer.removeClass(this.document.body, "mat-color-scheme-light")
        break;
      case Theme.Light:
        this.renderer.addClass(this.document.body, "mat-color-scheme-light")
        this.renderer.removeClass(this.document.body, "mat-color-scheme-dark")
        break;
    }
    

    ColorModeService.ThemeChangeSubscribers.forEach(sbc => sbc(theme));

    const element = this.document.documentElement;
    if (theme === Theme.Auto) {
      const preferredTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? Theme.Dark : Theme.Light;
      this.renderer.setAttribute(element, 'data-bs-theme', preferredTheme);
    } else {

      this.renderer.setAttribute(element, 'data-bs-theme', theme);
    }
  }

  private static ThemeChangeSubscribers: Array<(theme: Theme) => void> = new Array();
}

export enum Theme {
  Dark = 'dark',
  Light = 'light',
  Auto = 'auto'
}

export const ParseTheme: (value: string) => Theme | undefined = (value: string) => {
  switch (value) {
    case Theme.Dark:
      return Theme.Dark;
    case Theme.Light:
      return Theme.Light;
    case Theme.Auto:
      return Theme.Auto;
    default:
      return undefined;
  }
}

export function GetLocalTheme(): Theme {
  let sTheme: string | null = (typeof window !== 'undefined') ? (localStorage.getItem('theme')) : 'dark';

  if (sTheme === null)
    return Theme.Dark;

  return ParseTheme(sTheme) ?? Theme.Dark;
}

export const GetWinDefaultTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches ? Theme.Dark : Theme.Light;