// @ts-check
/**
 * An ESLint rule that ensures all files have a C-style header, just like this one.
 */

import { ESLintUtils } from "@typescript-eslint/utils"

const defaultHeaderContent = "*\n * Describe this file here!\n "
const defaultHeader = `/*${defaultHeaderContent}*/\n\n`


export default ESLintUtils.RuleCreator.withoutDocs({
    meta: {
        type: "problem",
        hasSuggestions: true,
        fixable: "code",
        messages: {
            "no-header": "Label things with comments! " +
                "Every file should have a C-style comment at the top explaining what that file does " +
                "(Reference existing files if you don't know what that is).",
            "default-header": "Describe what this file does. If there is a good reason not to, replace this with /**/"
        },
        schema: [],
    },
    defaultOptions: [],
    create(context) {
        return {
            Program(node) {
                const continuousComments = node.comments
                    .slice(0,1)
                    // Comments must start at the beginning of the file
                    .filter(c => c.range[0] === 0)
                if(continuousComments.length > 0) {
                    // Find an array of continuous comments, that have no code in between
                    for(const comment of node.comments.slice(1)) {
                        if(comment.range[0] - continuousComments[0].range[1] <= 2)
                            continuousComments.unshift(comment)
                        else break
                    }
                    continuousComments.reverse()

                    // Find the first occurence of a c-style comment
                    const block = continuousComments.find(c => c.type === "Block")
                    if(block) {
                        if(block.value === defaultHeaderContent)
                            return context.report({
                                node: block,
                                messageId: "default-header",
                            })
                        // Good, there is a comment which is not default
                        return
                    }
                }

                // No comments at all or no block comment at the top
                return context.report({
                    node,
                    messageId: "no-header",

                    fix: (fixer) => [
                        fixer.insertTextBefore(node, defaultHeader)
                    ]
                })
            }
        }
    },
})
