import { BorderRadius } from '../constants/tokens/border-radius';
import { Colors } from '../constants/tokens/colors';
import { Spacing } from '../constants/tokens/spacing';
import { Breakpoints } from '../constants/tokens/breakpoints';
import { Shadows } from '../constants/tokens/shadows';
import { LogUtility } from './log';
import { isBackgroundColorTokenType, isBorderColorTokenType, isBorderRadiusTokenType, isBorderStyleType, isBorderTokenType, isBreakpointsTokenType, isShadowsTokenType, isSpacingTokenType, isTextColorTokenType, isTypographyTokenType, } from '../types/type-guard';
import ResponsiveFormatFacade from '../helpers/formatter/responsive-map-formatter/responsive-format-facade';
import { TypographyKeys } from '../constants/tokens/typography';
import { Borders } from '../constants/tokens/borders';
import StateFormatFacade from '../helpers/formatter/state-formatter/state-format-facade';
import { BorderStyle } from '../constants/ui';
/**
 * It logs a warning message to the console.
 *
 * @param {string} tokenType - The name of the token type.
 * @param {unknown} value - The value that was passed into the token.
 * @param {unknown} availableOptions - The available options for the token type.
 */
function logInvalidValueMessage(tokenType, value, availableOptions) {
  LogUtility.warn(`The ${tokenType} value ${value} is invalid, it must be a value of: `, availableOptions);
}
/**
 * Given a token and an array of modes, return a string with the token formatted with the appropriate mode
 *
 * @param {string} token - The name of the token.
 * @param {TokenMode[]} modes - TokenMode[]
 * @returns {string} The formatted token.
 */
function formatTokenWithModes(token, modes) {
  let formattedToken = '';
  if (modes.includes('dark')) {
    formattedToken += ` dark:v-dark-${token}`;
  }
  return formattedToken;
}
/**
 * If the token is a valid spacing token, return the CSS class string. Otherwise, log an error message
 *
 * @param {unknown} token - The value that was passed into the function.
 * @returns {Nullable<string>} The the CSS class string of the padding token.
 */
export function formatAndValidPadding(token) {
  if (isSpacingTokenType(token)) {
    return `v-p-${token}`;
  }
  else {
    logInvalidValueMessage('padding', token, Object.keys(Spacing));
  }
}
/**
 * The function `formatAndValidBorderStyle` formats a border style token and returns a string if it is
 * a valid border style type, otherwise it logs an invalid value message.
 *
 * @param {unknown} token - The `token` parameter is a value that represents a border style type.
 * @returns {Nullable<string>} The function `formatAndValidBorderStyle` returns a string that is formatted as
 * `v-border-` if the `token` parameter is of a valid border style type. If the `token` is not
 * a valid border style type, it logs an invalid value message and does not return anything (implicitly
 * returns `undefined`).
 */
export function formatAndValidBorderStyle(token) {
  if (isBorderStyleType(token)) {
    return `v-border-${token}`;
  }
  else {
    logInvalidValueMessage('border-style', token, BorderStyle);
  }
}
/**
 * If the token is a valid border radius, return a string with the token prefixed with `v-rounded-`. Otherwise, log an
 * error message
 *
 * @param {unknown} token - The value passed in by the user.
 * @returns {Nullable<string>} The the CSS class string of the border radius token.
 */
export function formatAndValidBorderRadius(token) {
  if (isBorderRadiusTokenType(token)) {
    return `v-${token}`;
  }
  else {
    logInvalidValueMessage('border-radius', token, Object.keys(BorderRadius));
  }
}
/**
 * If the token is a valid border color, return CSS class string of the border color. Otherwise, log an error message
 *
 * @param {unknown} token - The value passed in by the user.
 * @returns {Nullable<string>}  return the CSS class string of the border color
 */
export function formatAndValidBorderColor(token) {
  if (isBorderColorTokenType(token)) {
    return `v-${token}`;
  }
  else {
    logInvalidValueMessage('border-color', token, Colors.filter(() => /^border-color-.+$/.test));
  }
}
/**
 * If the token is a valid border, return CSS class string of the border. Otherwise, log an error message
 *
 * @param {unknown} token - The value passed in by the user.
 * @returns {Nullable<string>}  return the CSS class string of the border
 */
export function formatAndValidBorder(token) {
  if (isBorderTokenType(token)) {
    return `v-${token}`;
  }
  else {
    logInvalidValueMessage('border', token, Borders.filter(() => /^border-.+$/.test));
  }
}
/**
 * If the token is a valid background color, return it with the v- prefix. Otherwise, log an error
 *
 * @param {unknown} token - The value of the token.
 * @param {TokenMode[]} withModes - TokenMode[] = []
 * @returns {Nullable<string>} CSS class string for the background color token with modes supported.
 */
export function formatAndValidBackgroundColor(token, withModes = []) {
  if (isBackgroundColorTokenType(token)) {
    return `v-${token}` + formatTokenWithModes(token, withModes);
  }
  else {
    logInvalidValueMessage('background-color', token, Colors.filter(() => /^bg-.+$/.test));
  }
}
/**
 * If the token is a valid text color, return the token prefixed with `v-` and formatted with the given modes. Otherwise,
 * log an error
 *
 * @param {unknown} token - The token to format.
 * @param {TokenMode[]} withModes - TokenMode[] = []
 * @returns {Nullable<string>} A CSS class string that is either a valid color or a valid color with modes.
 */
export function formatAndValidTextColor(token, withModes = []) {
  if (isTextColorTokenType(token)) {
    return `v-${token}` + formatTokenWithModes(token, withModes);
  }
  else {
    logInvalidValueMessage('text-color', token, Colors.filter(() => /^text-.+$/.test));
  }
}
/**
 * If the token is a valid breakpoint, return CSS class string for the flex breakpoint. Otherwise, log an error
 *
 * @param {unknown} token - The value of the breakpoint.
 * @returns {Nullable<string>} CSS class string for the flex breakpoint.
 */
export function formatAndValidFlexBreakpoint(token) {
  if (isBreakpointsTokenType(token)) {
    return `vega-flex-${token}`;
  }
  else {
    logInvalidValueMessage('breakpoint', token, Object.keys(Breakpoints));
  }
}
/**
 * If the token is a breakpoint, return the breakpoint value. Otherwise, log an error and return 0
 *
 * @param {unknown} token - The value passed in by the user.
 * @returns {Nullable<number>} value of the breakpoint.
 */
export function formatAndValidBreakpointSize(token) {
  if (isBreakpointsTokenType(token)) {
    return Breakpoints[token];
  }
  else {
    logInvalidValueMessage('breakpoint', token, Object.keys(Breakpoints));
  }
}
/**
 * If the token is a valid spacing token, return a string with the token name prefixed with `v-gap-`. Otherwise, log an
 * error message
 *
 * @param {unknown} token - The value passed in by the user.
 * @returns {Nullable<string>} CSS class string for the given gap token.
 */
export function formatAndValidGap(token) {
  if (isSpacingTokenType(token)) {
    return `v-gap-${token}`;
  }
  else {
    logInvalidValueMessage('gap', token, Object.keys(Spacing));
  }
}
/**
 * If the token is a valid shadows token type, return the token with the prefix "v-". Otherwise, log an error message
 *
 * @param {string} token - The token to format.
 * @param {TokenMode[]} withModes - TokenMode[] = []
 * @returns {Nullable<string>} CSS class string of the shadow token with modes supported
 */
export function formatAndValidShadow(token, withModes = []) {
  if (isShadowsTokenType(token)) {
    return `v-${token}` + formatTokenWithModes(token, withModes);
  }
  else {
    logInvalidValueMessage('shadows', token, Shadows);
  }
}
/**
 * It takes a token and a flag, and returns a string
 *
 * @typedef Flag key of ManagedResponsiveScopeInput
 * @param {ResponsiveType<ManagedResponsiveScopeInput[Flag]>} token - The token to format.
 * @param {Flag} flag - The flag that the token is being formatted for.
 * @returns {Nullable<ManagedResponsiveScopeOutput[Flag]>} A nullable string
 */
export function formatAndValidResponsiveToken(token, flag) {
  if (token !== null && token !== undefined) {
    return ResponsiveFormatFacade.format(token, flag);
  }
}
/**
 * The function `formatAndValidTypographyToken` formats a typography token by adding a prefix and checks if it is a valid typography token.
 *
 * @param {string} token - The `token` parameter is a string that represents a typography token.
 * @returns {Nullable<string>} a string value.
 */
export function formatAndValidTypographyToken(token) {
  if (isTypographyTokenType(token)) {
    return `v-${token}`;
  }
  else {
    logInvalidValueMessage('font', token, TypographyKeys);
  }
}
/**
 * The function `formatAndValidStateToken` formats and validates a state token based on a specified flag.
 *
 * @param {StateVariantType} token - The `token` parameter is a value that represents a state variant for a specific flag
 * in a managed state scope input.
 * @param {Flag} flag - The `flag` parameter is a key of the `ManagedStateScopeInput` type.
 * @returns {Nullable<string>} a formatted and validated state token as a string, or `null` if the input token is `null`
 * or `undefined`.
 */
export function formatAndValidStateToken(token, flag) {
  if (token !== null && token !== undefined) {
    return StateFormatFacade.format(token, flag);
  }
}
