#!/usr/bin/env node
/**
 * Copyright (c) HashiCorp, Inc.
 * SPDX-License-Identifier: BUSL-1.1
 */

/* eslint-env node */
/**
 * Codemod to transform Icon component to new API to accomodate FlightIcon
 * example execution from ui directory -> npx ember-template-recast ./templates -t ./scripts/codemods/icon-transform.js
 * above will run transform on all files in templates directory
 */

module.exports = (env) => {
  const {
    syntax: { builders },
  } = env;
  const hsSizes = ['s', 'm', 'l', 'xlm', 'xl', 'xxl'];

  // find attribute by name
  const findAttribute = (attrs, name) => {
    for (let i = 0; i < attrs.length; i++) {
      if (attrs[i].name === name) {
        return [attrs[i], i, attrs[i].value.chars];
      }
    }
    return [];
  };

  // possibly a bug with ember-template-recast for multi line components with attributes on their own lines
  // when removing an attribute the one on the line below will jump to the same line as the previous one
  // this does not happen when removing the first attribute -- doing so may add unnecessary quotes to the first shifted attribute
  // example: class="{{foo}}" -> class=""{{foo}}""
  const preserveFormatting = (attributes, removeIndex) => {
    if (removeIndex > 0) {
      // shift the location of the attributes that appear after the one being removed to preserve formatting
      for (let i = attributes.length - 1; i > removeIndex; i--) {
        attributes[i].loc = attributes[i - 1].loc;
      }
    }
  };

  // transform structure icon size letter to flight icon supported size
  const transformSize = (attributes, attrName) => {
    const [attr, attrIndex, value] = findAttribute(attributes, attrName);

    if (hsSizes.includes(value)) {
      if (['s', 'm', 'l'].includes(value)) {
        // before removing attribute set the location of the remaining attributes
        preserveFormatting(attributes, attrIndex);
        // since 16 is the default in the component we can remove the attribute
        attributes.splice(attrIndex, 1);
      } else {
        attr.value = builders.text('24');
        // rename attribute
        if (attrName === '@sizeClass') {
          attr.name = '@size';
        }
      }
    }
  };

  return {
    ElementNode(node) {
      if (node.tag === 'Icon') {
        const { attributes } = node;
        // the inital refactor of the component introduced a sizeClass attribute
        // this can now be mapped to size and removed
        transformSize(attributes, '@sizeClass');
        // check for old component instances that may still have a letter for size value
        transformSize(attributes, '@size');
      }
    },
  };
};
