/* eslint-disable @typescript-eslint/no-var-requires */
const { template, camelCase, cloneDeep } = require('lodash')

const variablesTemplate = template(`import { css } from '@emotion/react'
export const variables = css\`
  :root {
    <%= cssVariables %>
  }\`
export const theme = {
  <%= themeVariables %>
}
export const cVar = (key: keyof typeof theme, returnValue?: boolean) => {
  if (returnValue) return theme[key].value
  return theme[key].variable
}
`)

module.exports = {
  source: [`./src/styles/tokens/**/*.json`],
  parsers: [
    {
      pattern: /\.json$/,
      parse: ({ contents }) => {
        // style dictionary requires adding ".value" suffix to all referenced value,  e.g.  "value": "{core.neutral.default.900}" should be  e.g.  "value": "{core.neutral.default.900.value}"
        // this parser should fix it, although it just a workaround
        // we could remove this when they do something about it https://github.com/amzn/style-dictionary/issues/721
        const parsed = contents.replace(/}"|\.value}"/g, `.value}"`)
        return JSON.parse(parsed)
      },
    },
    // creates filterEffects design tokens, which are needed to use for `filter: drop-shadow()`
    {
      pattern: /\.json$/,
      parse: ({ contents }) => {
        const obj = JSON.parse(contents)
        if (obj.effect) {
          const deepCopy = cloneDeep(obj)
          deepCopy.filterEffect = deepCopy.effect
          delete deepCopy.effect
          return { ...obj, ...deepCopy }
        }
      },
    },
  ],
  transform: {
    removeDefaultFromName: {
      type: 'name',
      transformer: (token) => token.name.replace(/-default|-regular/g, ''),
    },
    easingTransform: {
      type: 'value',
      matcher: (token) => token.attributes.type === 'easing',
      // [1, 2, 3, 4] will become 1, 2, 3, 4
      transformer: (token) => `cubic-bezier(${token.value.toString().replace(/\[|\]/g, '')})`,
    },
    transitionTransform: {
      type: 'value',
      transitive: true,
      matcher: (token) => token.attributes.type === 'transition',
      transformer: (token) => `${token.value.timing} ${token.value.easing}`,
    },
    typographyValueTransform: {
      type: 'value',
      transitive: true,
      matcher: (token) => token.attributes.type === 'textStyles',
      transformer: (token) =>
        `${token.value.fontWeight} ${token.value.fontSize}/${token.value.lineHeight} ${token.value.fontFamily}`,
    },
    typographyNameTransform: {
      type: 'name',
      matcher: (token) => token.attributes.type === 'textStyles',
      transformer: (token) => token.name.replace(/-heading|-text|-styles/g, ''),
    },
    effectsTransform: {
      type: 'value',
      transitive: true,
      matcher: (token) => token.attributes.category === 'effect',
      transformer: (token) => {
        const isDivider = token.attributes.type === 'dividers'
        return `${isDivider ? 'inset' : ''} ${token.value.x} ${token.value.y} ${token.value.blur} ${
          token.value.spread
        } ${token.value.color}`
      },
    },
    filterEffectsTransform: {
      type: 'value',
      transitive: true,
      matcher: (token) => token.attributes.category === 'filterEffect',
      transformer: (token) => `drop-shadow(${token.value.x} ${token.value.y} ${token.value.blur} ${token.value.color})`,
    },
  },
  format: {
    customFormat: ({ dictionary }) => {
      // create new tokens for letter-spacing
      const allTokens = dictionary.allTokens
      const letterSpacingTokens = allTokens
        .filter((token) => token.attributes.type === 'textStyles')
        .map((token) => ({
          ...token,
          value: token.original.value.letterSpacing || 0,
          name: `${token.name}-letter-spacing`,
        }))

      // create new tokens for text-transform
      const textTransformTokens = allTokens
        .filter((token) => token.attributes.type === 'textStyles')
        .map((token) => ({
          ...token,
          value: token.original.value.textTransform || 'none',
          name: `${token.name}-text-transform`,
        }))

      const convertedTokens = [...allTokens, ...letterSpacingTokens, ...textTransformTokens]
      return variablesTemplate({
        cssVariables: convertedTokens
          .map((token) => {
            let keyValuePair = `--${token.name}: ${token.value};`
            if (dictionary.usesReference(token.original.value)) {
              const refs = dictionary.getReferences(token.original.value)

              refs.forEach((ref) => {
                const [key, value] = keyValuePair.split(':')
                const modifiedValue = value.replace(ref.value, `var(--${ref.name})`)
                keyValuePair = `${key}:${modifiedValue}`
              })
            }
            return keyValuePair
          })
          .join('\n'),
        themeVariables: convertedTokens
          .map((token) => `${camelCase(token.name)}: { variable: 'var(--${token.name})', value: '${token.value}' },`)
          .join('\n'),
      })
    },
  },
  platforms: {
    ts: {
      transforms: [
        `attribute/cti`,
        `name/cti/kebab`,
        'removeDefaultFromName',
        'typographyValueTransform',
        'typographyNameTransform',
        'easingTransform',
        'transitionTransform',
        'effectsTransform',
        'filterEffectsTransform',
      ],
      buildPath: 'src/styles/generated/',
      files: [
        {
          destination: 'variables.ts',
          format: 'customFormat',
          filter: (token) => token.type !== 'typedef',
          options: {
            outputReferences: true,
          },
        },
      ],
    },
  },
}
