import { CSSProperties } from 'glamor';
import { TokenType } from '../../themes/token.interface';
import { StyleType } from '../../themes/style.interface';
import { PaletteType } from '../../themes/palette.interface';

export interface TypographyStyles {
  a?: CSSProperties;
  caption: CSSProperties;
  emphasis?: CSSProperties;
  header: CSSProperties;
  label?: CSSProperties;
  large: CSSProperties;
  standard: CSSProperties;
  subheader: CSSProperties;
  subtitle: CSSProperties;
  title: CSSProperties;
  underlined: CSSProperties;
  accent: CSSProperties;
}

export type BodyStyles = CSSProperties;

export interface LayoutStyles {
  horizontal: CSSProperties;
  overlay: CSSProperties;
  vertical: CSSProperties;
}

export interface InputStyles {
  xs: CSSProperties;
  s: CSSProperties;
  m: CSSProperties;
  l: CSSProperties;
  xl: CSSProperties;
  xxl: CSSProperties;
  xxxl: CSSProperties;
}

export interface UtilityStyles {
  truncateWithEllipsis: CSSProperties;
  fadeInView: CSSProperties;
  disabled: CSSProperties;
}

export interface BackgroundStyles {
  forTransparency: CSSProperties;
  overlay?: CSSProperties;
  menu: CSSProperties;
  darkColor: CSSProperties;
  lightColor: CSSProperties;
}

export interface SeparatorStyles {
  horizontal: CSSProperties;
  vertical: CSSProperties;
}

export interface FocusStyles {
  mouse: CSSProperties;
  keyboard: CSSProperties;
}

export interface LoadingStyles {
  circular: CSSProperties;
  linear: CSSProperties;
}

export interface BoxSizeStyles {
  xs: CSSProperties;
  s: CSSProperties;
  m: CSSProperties;
  l: CSSProperties;
  xl: CSSProperties;
  xxl: CSSProperties;
  xxxl: CSSProperties;
}

/**
 * Type definition for general/global app styles
 */
export type BaseStyleTypeOption =
  | 'focus'
  | 'typography'
  | 'layout'
  | 'separator'
  | 'background'
  | 'button'
  | 'body'
  | 'input'
  | 'icon'
  | 'utility'
  | 'loading';
/**
 * Type definition for general/global app styles
 */
export interface ThemeStyles {
  focus: FocusStyles;
  /**
   * Styles to be applied for text when using this theme
   */
  typography: TypographyStyles;
  /**
   * Layout styles used to organize elements on the screen
   */
  layout: LayoutStyles;
  /**
   * Layout for separators
   */
  separator: SeparatorStyles;
  /**
   * Styles for specific background elements
   */
  background: BackgroundStyles;
  /**
   * Default styles to be applied to the root of a button element,
   * preferably a `<button>` element
   */
  button: ButtonStyleVariant;
  /**
   * Default styles to be applied to the root level component of the app of the page when using this theme
   */
  body: CSSProperties;
  /**
   * Default styles to be applied to inputs when using this theme
   */
  input: InputStyles;
  /**
   * Default styles to be applied to icons when using this theme
   */
  icon: CSSProperties;
  /**
   * helper styles to apply to perform a thing
   */
  utility: UtilityStyles;
  /**
   * Styles to be applied to loading components
   */
  loading: LoadingStyles;
  /**
   * Styles to be applied to sized boxed context,
   */
  boxSize: BoxSizeStyles;
}

/**
 * Type definition for general/global app styles
 * to be used when extending a theme
 * Do not use this type when creating a theme, only when extending
 */
export interface ExtendedThemeStyles {
  focus?: Partial<FocusStyles>;
  /**
   * Styles to be applied for text when using this theme
   */
  typography?: Partial<TypographyStyles>;
  /**
   * Layout styles used to organize elements on the screen
   */
  layout?: Partial<LayoutStyles>;
  /**
   * Layout for separators
   */
  separator?: Partial<SeparatorStyles>;
  /**
   * Styles for specific background elements
   */
  background?: Partial<BackgroundStyles>;
  /**
   * Default styles to be applied to the root of a button element,
   * preferably a `<button>` element
   */
  button?: Partial<ButtonStyleVariant>;
  /**
   * Default styles to be applied to the root level component of the app of the page when using this theme
   */
  body?: Partial<CSSProperties>;
  /**
   * Default styles to be applied to inputs when using this theme
   */
  input?: Partial<InputStyles>;
  /**
   * Default styles to be applied to icons when using this theme
   */
  icon?: Partial<CSSProperties>;
  /**
   * helper styles to apply to perform a thing
   */
  utility?: Partial<UtilityStyles>;
  /**
   * Styles to be applied to loading components
   */
  loading?: Partial<LoadingStyles>;
}

/**
 * Buttons options for appearance
 */
export type ButtonAppearanceOptions =
  | 'brand'
  | 'brandClear'
  | 'clear'
  | 'destructive'
  | 'primary'
  | 'secondary'
  | 'select'
  | 'tab'
  | 'tertiary';

/**
 * Buttons options for sizes
 */
export type ButtonSizeOptions = 'small' | 'medium' | 'large';

/**
 * Buttons options for style variants
 */
export type ButtonVariantOptions = 'borderless';
/**
 * Buttons options for state variants
 */
export type ButtonStateOptions = 'disabled';

/**
 * Buttons Styles Variant Type
 */
export type ButtonStyleVariant = Record<ButtonAppearanceOptions, CSSProperties>;

export interface FontFamilyTokensType {
  text?: string;
  brand?: string;
  accent?: string;
  heading?: string;
  default: string;
  monospace?: string;
}
/**
 * Interface to be used when applying font sizes
 */
export interface FontSizeTokensType {
  /**
   * Small font size to be used in small text
   */
  small: string;
  /**
   * Font size to be used in captions
   */
  caption: string;
  /**
   * Large font size to be used in large text
   */
  large: string;
  /**
   * Font size to be used in legal text
   */
  legal: string;
  /**
   * Font size to be used in subheader
   */
  subheader: string;
  /**
   * Font size to be used in subtitles
   */
  subtitle: string;
  /**
   * Font size to be used in titles
   */
  title: string;
  /**
   * Font size to be used in standard text, usually the predominant size throughout all components
   */
  standard: string;
  /**
   * Font size to be used in Tags
   */
  tag: string;
  /**
   * Font sizes to be applied to primary headings
   */
  header: string;
  standardLarge: string;
  standardSmall: string;
}

/**
 * Interface to be applied to font weights
 */
export interface FontWeightTokensType {
  light: number;
  standard: number;
  bold: number;
  bolder: number;
  extraBold: number;
}

/**
 * Interface to define border width values
 */
export interface BorderWidthTokensType {
  none: string;
  thin: string;
  default: string;
}

/**
 * Interface to define line heights
 */
export interface LineHeightTokensType {
  /**
   * Small font size to be used in small text
   */
  small: string;
  /**
   * Font size to be used in captions
   */
  caption: string;
  /**
   * Large font size to be used in large text
   */
  large: string;
  /**
   * Font size to be used in legal text
   */
  legal: string;
  /**
   * Font size to be used in subheader
   */
  subheader: string;
  /**
   * Font size to be used in subtitles
   */
  subtitle: string;
  /**
   * Font size to be used in titles
   */
  title: string;
  /**
   * Font size to be used in standard text, usually the predominant size throughout all components
   */
  standard: string;
  /**
   * Font size to be used in Tags
   */
  tag: string;
  /**
   * Font sizes to be applied to primary headings
   */
  header: string;
  standardLarge: string;
  standardSmall: string;
}

/**
 * Interface to define media queries for various screen sizes
 */
export interface MediaQueryTokensType {
  /**
   * Defines media query for extra small screens
   */
  xs: string;
  /**
   * Defines media query for  small screens
   */
  s: string;
  /**
   * Defines media query for medium screens
   */
  m: string;
  /**
   * Defines media query for large screens
   */
  l: string;
  /**
   * Defines media query for extra large screens
   */
  xl: string;
  /**
   * Defines media query for non small screens
   */
  nonSmallScreens: string;
  /**
   * Defines media query for  small screens
   */
  smallScreens: string;
}

/**
 * Interface to define opacity values
 */
export interface OpacityTokensType {
  /**
   * Value to be applied when you want to make the current value disappear
   * completely
   */
  none: number;
  /**
   * Value to be applied when you want to obtain approximately half opacity
   * of the current value. Suggested value is 0.5
   */
  dimmed: number;
  /**
   * Value to be applied when you want to obtain approximately just about a
   * quarter less opacity of the current value. Suggested value is 0.75
   */
  faded: number;
}

/**
 * Interface to define radius values
 */
export interface RadiusTokensType {
  /**
   * Radius size value for circles. Suggested value is 50%
   */
  circle: string;
  default: string;
  /**
   * Extra small size radius value
   */
  xs: string;
  /**
   * Small size radius value
   */
  s: string;
  /**
   * Medium size radius value
   */
  m: string;
  /**
   * Large size radius value
   */
  l: string;
  /**
   * Extra large size radius value
   */
  xl: string;
}

/**
 * Interface to define spacing values
 * These values are to be applied to spacings in grids, paddings and margins to separate
 * blocks of content
 */
export interface SpacingsTokensType {
  /**
   * Default value to be used when separating blocks of content
   */
  default: string | number;
  /**
   * Value to clear previous spacings or remove spacing. Suggested value is 0
   */
  none: string | number;
  /**
   * Default gutter size to be applied in layout grids
   */
  gutter: string | number;
  one: string | number;
  xxs: string | number;
  xs: string | number;
  s: string | number;
  m: string | number;
  r: string | number;
  l: string | number;
  xl: string | number;
  xxl: string | number;
  xxxl: string | number;
}
/**
 * Interface for styles to be applied to text
 */
export interface FontStyleTokensType {
  /**
   * Style to be used when referencing text with quotes
   */
  quote: string;
}

/**
 * Interface to define values for zIndexes
 */
export interface ZIndexTokensType {
  /**
   * z Index value for elements off screen
   */
  offscreen?: number;
  /**
   * The base zIndex value (zIndexes can go above or below this value)
   */
  default: number;
  /**
   * z Index value for popups
   */
  popup?: number;
  /**
   * z Index value for menus
   */
  menu?: number;
  /**
   * z Index value for overlays
   */
  overlay?: number;
  /**
   * z Index value for toast/notifications
   */
  toast?: number;
  panel?: number;
}
/**
 * Interface to define Icon sizes
 */
export interface IconSizeTokensType {
  xs: string | number;
  /**
   * Defines the size for a small size icon
   */
  s: string | number;
  /**
   * Defines the size for a medium size icon
   */
  m: string | number;
  /**
   * Defines the size for a large icon
   */
  l: string | number;
  /**
   * Defines the size for a extra large icon
   */
  xl: string | number;
  /**
   * Defines the size for a extra extra large icon
   */
  xxl: string | number;
  /**
   * Defines the size for a extra extra extra large icon
   */
  xxxl: string | number;
}

export interface FocusRingColorTokens {
  /**
   * Defines the color for the inner border of the focus ring
   */
  inset: string;
  /**
   * Defines the color for the outer most outline of the focus ring
   */
  outline: string;
}

/**
 * These colors will be the same for any theme
 */
export interface CommonColors {
  brand: string;
  brandAlt: string;
  error: string;
  info: string;
  onBrand: string;
  onBrandAlt: string;
  onError: string;
  onInfo: string;
  onSuccess: string;
  onWarning: string;
  required: string;
  success: string;
  toggleOn: string;
  warning: string;
  lightColor: string;
  darkColor: string;
}

export interface ThemedColors {
  background: string;
  onBackground: string;
  borderOnPrimary: string;
  borderOnPrimaryInverse: string;
  borderOnSurface: string;
  borderOnSurface10: string;
  focusRingInset: string;
  focusRingOutline: string;
  onPrimary_10: string;
  onPrimary_20: string;
  onPrimary_40: string;
  onPrimary_50: string;
  onPrimary_90: string;
  onPrimary_95: string;
  onPrimary: string;
  onPrimaryInverse_70: string;
  onPrimaryInverse: string;
  onSelection: string;
  onSurface: string;
  onSurface10: string;
  onSurface20: string;
  onSurface30: string;
  onSurface40: string;
  overlay: string;
  primary: string;
  primaryInverse: string;
  selection: string;
  surface: string;
  surface10: string;
  surface20: string;
  surface30: string;
  surface40: string;
}
/**
 * Includes all themed colors in the theme
 */
export interface ThemeColors extends CommonColors, ThemedColors {}

export interface ThemedExtendedTokensType
  extends Partial<CommonColors>,
    Partial<ThemedColors> {}

/**
 * Theme mode independent design tokens
 */
export interface ThemeTokens {
  /** Defines border widths */
  borderWidth: BorderWidthTokensType;
  /** Defines font families */
  fontFamily: FontFamilyTokensType;
  /** Defines font sizes */
  fontSize: FontSizeTokensType;
  /** Defines thickness for letters in fonts */
  fontWeight: FontWeightTokensType;
  /** Defines icon sizes */
  iconSize: IconSizeTokensType;
  /** Defines line heights */
  lineHeight?: LineHeightTokensType;
  /** Defines media queries */
  mediaQuery: MediaQueryTokensType;
  /** Defines opacities */
  opacity?: OpacityTokensType;
  /** Defines radius values */
  radius: RadiusTokensType;
  /** Defines spacings */
  spacings: SpacingsTokensType;
  /** Defines z indexes */
  zIndex: ZIndexTokensType;
}

/**
 * Interface to extend design tokens
 * This interface is used to extend the design tokens of a theme
 * Do not use this interface to create a theme, only when extending a theme
 */
export interface ExtendedThemeTokens {
  /** Defines border widths */
  borderWidth?: Partial<BorderWidthTokensType>;
  /** Defines <font families */
  fontFamily?: Partial<FontFamilyTokensType>;
  /** Defines font sizes */
  fontSize?: Partial<FontSizeTokensType>;
  /** Defines thickness for letters in fonts */
  fontWeight?: Partial<FontWeightTokensType>;
  /** Defines icon sizes */
  iconSize?: Partial<IconSizeTokensType>;
  /** Defines line heights */
  lineHeight?: Partial<LineHeightTokensType>;
  /** Defines media queries */
  mediaQuery?: Partial<MediaQueryTokensType>;
  /** Defines opacities */
  opacity?: Partial<OpacityTokensType>;
  /** Defines radius values */
  radius?: Partial<RadiusTokensType>;
  /** Defines spacings */
  spacings?: Partial<SpacingsTokensType>;
  /** Defines z indexes */
  zIndex?: Partial<ZIndexTokensType>;
}
/**
 * Interface for global App theme definition
 */
export interface ApphouseTheme {
  /**
   * A unique identifier for the theme
   */
  id?: string;
  /**
   * Defines a set of tokens that change values depending on the selected
   * color theme
   */
  colors: ThemeColors;
  /**
   * Defines a set of tokens that are theme independent
   */
  tokens: ThemeTokens;
  /**
   * Defines a set of styles for common sets of design tokens
   */
  styles: ThemeStyles;
}

/**
 * Interface for extended App theme definition
 * This interface is used to extend the theme with custom tokens
 * and styles
 * Only the properties that are extended need to be defined
 * The rest of the properties will be inherited from the ApphouseTheme interface
 * Do not use this interface without extending the ApphouseTheme interface
 */
export interface ExtendedApphouseTheme {
  /**
   * A unique identifier for the theme
   */
  id?: string;
  /**
   * Defines a set of tokens that change values depending on the selected
   * color theme
   */
  colors?: Partial<ThemeColors>;
  /**
   * Defines a set of tokens that are theme independent
   */
  tokens?: Partial<ExtendedThemeTokens>;
  /**
   * Defines a set of styles for common sets of design tokens
   */
  styles?: Partial<ExtendedThemeStyles>;
}

export interface ThemeFull {
  id: string;
  title: string;
  colors: PaletteType[];
  tokens: TokenType[];
  styles: StyleType[];
}

export interface ThemeFlat {
  id: string;
  title: string;
  tokens: object;
  colors: Record<string, object>;
  styles: Record<string, any>;
}
