/**
 * @author Yosuke Ota
 * See LICENSE file in root directory for full license.
 */
'use strict'
module.exports = {
  supported: '2.6.0',
  createTemplateBodyVisitor (context) {
    const sourceCode = context.getSourceCode()

    /**
     * Checks whether the given node can convert to the `slot`.
     * @param {VAttribute} vSlotAttr node of `v-slot`
     * @returns {boolean} `true` if the given node can convert to the `slot`
     */
    function canConvertToSlot (vSlotAttr) {
      if (vSlotAttr.parent.parent.name !== 'template') {
        return false
      }
      return true
    }
    /**
     * Convert to `slot` and `slot-scope`.
     * @param {object} fixer fixer
     * @param {VAttribute} vSlotAttr node of `v-slot`
     * @returns {*} fix data
     */
    function fixVSlotToSlot (fixer, vSlotAttr) {
      const key = vSlotAttr.key
      if (key.modifiers.length) {
        // unknown modifiers
        return null
      }

      const attrs = []
      const argument = key.argument
      if (argument) {
        if (argument.type === 'VIdentifier') {
          const name = argument.rawName
          attrs.push(`slot="${name}"`)
        } else if (argument.type === 'VExpressionContainer' && argument.expression) {
          const expression = sourceCode.getText(argument.expression)
          attrs.push(`:slot="${expression}"`)
        } else {
          // unknown or syntax error
          return null
        }
      }
      const scopedValueNode = vSlotAttr.value
      if (scopedValueNode) {
        attrs.push(
          `slot-scope=${sourceCode.getText(scopedValueNode)}`
        )
      }
      if (!attrs.length) {
        attrs.push('slot') // useless
      }
      return fixer.replaceText(vSlotAttr, attrs.join(' '))
    }
    /**
     * Reports `v-slot` node
     * @param {VAttribute} vSlotAttr node of `v-slot`
     * @returns {void}
     */
    function reportVSlot (vSlotAttr) {
      context.report({
        node: vSlotAttr.key,
        messageId: 'forbiddenVSlot',
        // fix to use `slot` (downgrade)
        fix: fixer => {
          if (!canConvertToSlot(vSlotAttr)) {
            return null
          }
          return fixVSlotToSlot(fixer, vSlotAttr)
        }
      })
    }

    return {
      "VAttribute[directive=true][key.name.name='slot']": reportVSlot
    }
  }
}
