/**
 * @author Pig Fang
 * See LICENSE file in root directory for full license.
 */
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

const utils = require('../utils')

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

module.exports = {
  meta: {
    type: 'suggestion',
    docs: {
      description:
        'require shorthand form attribute when `v-bind` value is `true`',
      categories: undefined,
      url: 'https://eslint.vuejs.org/rules/prefer-true-attribute-shorthand.html'
    },
    fixable: null,
    hasSuggestions: true,
    schema: [{ enum: ['always', 'never'] }],
    messages: {
      expectShort:
        "Boolean prop with 'true' value should be written in shorthand form.",
      expectLong:
        "Boolean prop with 'true' value should be written in long form.",
      rewriteIntoShort: 'Rewrite this prop into shorthand form.',
      rewriteIntoLongVueProp:
        'Rewrite this prop into long-form Vue component prop.',
      rewriteIntoLongHtmlAttr:
        'Rewrite this prop into long-form HTML attribute.'
    }
  },
  /** @param {RuleContext} context */
  create(context) {
    /** @type {'always' | 'never'} */
    const option = context.options[0] || 'always'

    return utils.defineTemplateBodyVisitor(context, {
      VAttribute(node) {
        if (!utils.isCustomComponent(node.parent.parent)) {
          return
        }

        if (option === 'never' && !node.directive && !node.value) {
          context.report({
            node,
            messageId: 'expectLong',
            suggest: [
              {
                messageId: 'rewriteIntoLongVueProp',
                fix: (fixer) =>
                  fixer.replaceText(node, `:${node.key.rawName}="true"`)
              },
              {
                messageId: 'rewriteIntoLongHtmlAttr',
                fix: (fixer) =>
                  fixer.replaceText(
                    node,
                    `${node.key.rawName}="${node.key.rawName}"`
                  )
              }
            ]
          })
          return
        }

        if (option !== 'always') {
          return
        }

        if (
          !node.directive ||
          !node.value ||
          !node.value.expression ||
          node.value.expression.type !== 'Literal' ||
          node.value.expression.value !== true
        ) {
          return
        }

        const { argument } = node.key
        if (!argument) {
          return
        }

        context.report({
          node,
          messageId: 'expectShort',
          suggest: [
            {
              messageId: 'rewriteIntoShort',
              fix: (fixer) => {
                const sourceCode = context.getSourceCode()
                return fixer.replaceText(node, sourceCode.getText(argument))
              }
            }
          ]
        })
      }
    })
  }
}
