import { makeAutoObservable } from 'mobx';
import ColorUtils, { fromColorStringToRgbaObject } from './utils/color.utils';
import { ApphousePaletteModeOptions } from '../constants/constants';
import { THEMES } from './presets';
import { Colors } from './presets/commonColors';
import { ColorDefinition, ColorType } from './utils/color.interface';

export class Color {
  title?: string;
  id: string;
  color: ColorDefinition;

  constructor(color: ColorType) {
    this.title = color.title || '';
    this.id = color.id;
    this.color = color.color;

    makeAutoObservable(this);
  }

  get objectify(): ColorType {
    return {
      title: this.title,
      id: this.id,
      color: {
        hex: this.color.hex || '',
        hsl: this.color.hsl || {
          h: 0,
          s: 0,
          l: 0,
          a: 0
        },
        hsv: this.color.hsv || {
          h: 0,
          s: 0,
          v: 0,
          a: 0
        },
        oldHue: this.color.oldHue || 0,
        rgb: this.color.rgb || {
          r: 0,
          g: 0,
          b: 0,
          a: 0
        },
        source: this.color.source || ''
      }
    };
  }

  get rgbString(): string | undefined {
    const rgba = this.color.rgb;
    return ColorUtils.toRgbaStringFromRgbaObject(rgba);
  }

  setColor = (color: ColorDefinition) => {
    this.color = color;
  };

  setTitle = (title: string) => {
    this.title = title;
  };

  setId = (id: string) => {
    this.id = id;
  };
}

export const defaultColorIdTypes = [
  'brand',
  /**
   * A primary color is the color displayed most frequently across your
   * app's screens and components.
   */
  'primary',
  /**
   * Your primary color can be used to make a color theme for your app,
   * including dark and light primary color variants.
   */
  'primaryVariant',
  /**
   * A secondary color provides more ways to accent and distinguish your product. Having a secondary color is optional, and should be applied sparingly to accent select parts of your UI.

    If you don’t have a secondary color, your primary color can also be used to accent elements.

    Secondary colors are best for:

    Floating action buttons
    Selection controls, like sliders and switches
    Highlighting selected text
    Progress bars
    Links and headlines
   */
  'secondary',
  /**
   * Dark and light secondary variants
Just like the primary color, your secondary color can have dark and light variants. A color theme can use your primary color, secondary color, and dark and light variants of each color.
   */
  'secondaryVariant',
  /**
   * The background color appears behind scrollable content. The baseline background and surface color is #FFFFFF.
   */
  'background',
  /**
   * Surface colors affect surfaces of components, such as cards, sheets, and menus.
   */
  'surface',
  /**
   * Error color indicates errors in components, such as invalid text in a text field. The baseline error color is #B00020.
   */
  'error',
  'success',
  'warning',
  'onBackground',
  'onSurface',
  'onPrimary',
  'onSecondary',
  'onTertiary'
];

/**
 * Generate colors based on the colors for this app (theming things)
 * @param defaultTheme  'dark' | 'light' | 'base'
 * @returns
 */
export const getDefaultColors = (
  mode?: ApphousePaletteModeOptions
): ColorType[] => {
  let colors: ColorType[] = [];

  if (!mode) {
    return [];
  }
  let presetColors: any = Colors;
  if (mode === 'light') {
    presetColors = THEMES.APPHOUSE_LIGHT.colors;
  }
  if (mode === 'dark') {
    presetColors = THEMES.APPHOUSE_DARK.colors;
  }
  // get base colors
  colors = Object.keys(presetColors).map((colorId: string) => {
    const hex: string = presetColors[colorId] as string;
    return {
      id: colorId,
      title: colorId,
      color: { hex, rgb: fromColorStringToRgbaObject(hex) }
    };
  });
  return colors;
};
