const fs = require('fs')
const path = require('path')

const srcPath = path.join(__dirname, '..', 'src')

function findFiles(dirPath) {
    const result = []
    const entries = fs.readdirSync(dirPath, {withFileTypes: true})

    entries.forEach((entry) => {
        const entryPath = path.join(dirPath, entry.name)
        if (entry.isFile() && entry.name.endsWith('.ts')) {
            result.push(entryPath)
        } else if (entry.isDirectory()) {
            result.push(...findFiles(entryPath))
        }
    })

    return result
}

findFiles(srcPath).forEach((file) => {
    let src = fs.readFileSync(file, 'utf-8')

    // Fix wrong use of @type instead of @return.
    src = src.replace(/(\n +\* \@param [^\n]*\n +\* )\@type /g, (match, p1) => p1 + '@return ')
    
    // Remove square brackets and default values from @param lines.
    src = src.replace(/(\n +\* @param +\{[^\n]+\} +)\[(\w+)[^\]\n]*\]/g, (match, p1, p2) => p1 + p2)

    // Remove types from @param and @return lines.
    src = src.replace(/(\n +\* \@(?:param|returns?) *)([a-zA-Z0-9_]+ *)?(\{[^\n]*)/g, (match, p1, p2, p3) => {
        p2 = p2 || ''
        let brackets = 1;
        let end = 0;
        for (let i = 1; brackets > 0 && i < p3.length; i++) {
            if (p3[i] == '{') {
                brackets++
            } else if (p3[i] == '}') {
                brackets--
                end = i + 1
            }
        }
        p1 = p1.trimEnd().replace('@returns', '@return')
        p2 = p2.trim()
        p3 = p3.slice(end).trim().replace(/^([a-zA-Z0-9_]+) +/, '$1 ')
        if (!p2 && !p3) return ''
        return p1 + ' ' + p2 + (p2 && p3 ? ' ' + p3 : p3)
    })

    // Remove @type lines.
    src = src.replace(/\n +\* \@type .*\n/g, '\n')

    // Remove consecutive empty doc lines.
    src = src.replace(/\n *\* *(\n *\*\/? *\n)/g, (match, p1) => p1)

    // Remove empty docs.
    src = src.replace(/\n *\/\*\*[ \n\*]+\*\/ *\n/g, '\n')

    // Fix indentation.
    src = src.replace(/(\n +\* +(?:@param \w+|@return) )([^\n]*)((?:\n +\* +[^@\n][^\n]+)+)/g, (match, p1, p2, p3) => {
        const indent = p1.length
        p3 = p3.replace(/(\n +\*)( +)([^\n]+)/g, (match, p1, p2, p3) => {
            p2 = new Array(Math.max(0, indent - p1.length + 1)).join(' ')
            return p1 + p2 + p3
        })
        return p1 + p2 + p3
    })

    fs.writeFileSync(file, src)
})