import { CSSProperties } from 'glamor';
import { makeAutoObservable, toJS } from 'mobx';
import { toCss } from '../utils/style.utils';
import {
  BaseComponentStateTypeOption,
  BaseComponentTypeOption,
  CssPropertyStyle,
  StyleType,
  TagPreviewOption
} from './style.interface';

export class Style {
  id: string;
  variant: string;
  baseComponent: BaseComponentTypeOption;
  value: CssPropertyStyle[];
  state: BaseComponentStateTypeOption;
  previewWithTag?: TagPreviewOption;
  /**
   * The theme id for which this style is for
   */
  themeId?: string;
  /**
   * When style is copied or imported from another theme it will have a
   * reference to the original theme id
   */
  referenceThemeId?: string;

  constructor(props: StyleType) {
    const {
      id,
      value,
      baseComponent,
      variant,
      state,
      previewWithTag,
      referenceThemeId,
      themeId
    } = props;
    this.id = id;
    this.value = value;
    this.variant = variant;
    this.baseComponent = baseComponent;
    this.state = state || 'default';
    this.previewWithTag = previewWithTag;
    this.referenceThemeId = referenceThemeId || '';
    this.themeId = themeId || '';
    makeAutoObservable(this);
  }

  get objectify(): StyleType {
    return {
      id: this.id,
      variant: this.variant,
      baseComponent: this.baseComponent,
      value: toJS(this.value),
      state: this.state,
      previewWithTag: this.previewWithTag,
      themeId: this.themeId || '',
      referenceThemeId: this.referenceThemeId || ''
    };
  }
  get flatten(): object {
    const styles: CSSProperties = {};

    this.value.forEach((v) => {
      if (v.property) {
        styles[v.property] = v.value;
      }
    });

    return {
      id: this.id,
      variant: this.variant,
      baseComponent: this.baseComponent,
      value: styles,
      state: this.state,
      previewWithTag: this.previewWithTag,
      themeId: this.themeId || '',
      referenceThemeId: this.referenceThemeId || ''
    };
  }

  get code() {
    const value = this.value;
    return toCss(value);
  }

  get cssProperties(): CSSProperties {
    const styles: CSSProperties = {};

    this.value.forEach((v) => {
      if (v.property) {
        styles[v.property] = v.value;
      }
    });
    return styles;
  }

  get cssPropertiesWithTokens(): CSSProperties {
    const styles: CSSProperties = {};

    this.value.forEach((v) => {
      if (v.property) {
        styles[v.property] = v.value;
      }
    });
    return styles;
  }

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

  addStyle(style: CssPropertyStyle) {
    this.value = [...this.value, style];
  }

  setValue(value: CssPropertyStyle[]) {
    this.value = value;
  }

  setVariant(value: string) {
    this.variant = value;
  }

  setBaseComponent(baseComponent: string) {
    this.baseComponent = baseComponent;
  }

  setPreviewWithTag(tag: TagPreviewOption) {
    this.previewWithTag = tag;
  }

  setReferenceThemeId(themeId: string) {
    this.referenceThemeId = themeId;
  }
  setThemeId(themeId: string) {
    this.themeId = themeId;
  }
}
