import { defineConfig } from 'vite'
import { readFileSync } from 'fs'
import { join } from 'path'
import { minify } from 'html-minifier-next'
import { buildSync } from 'esbuild'

const ROOT = join(process.cwd(), 'application')
const DIST = join(ROOT, 'dist')

export default defineConfig({
    root: ROOT,
    build: {
        outDir: DIST,
        modulePreload: {
            polyfill: false,
        },
        rollupOptions: {
            input: [
                join(ROOT, 'index.html'),
                join(ROOT, 'not-found.html'),
                join(ROOT, 'qr-code.html'),
                join(ROOT, 'secret-sprites.html'),
                join(ROOT, 'secret-picross.html'),
                join(ROOT, 'about.html'),
            ],
            output: {
                hashCharacters: 'hex',
                entryFileNames: 'assets/[name].[hash].js',
                chunkFileNames: 'assets/[name].[hash].js',
                assetFileNames: 'assets/[name].[hash][extname]',
            },
        },
    },
    server: {
        strictPort: true,
        port: 5173,
    },
    plugins: [
        {
            name: 'server-uri',
            configureServer(server) {
                const includeDir = join(ROOT, 'include')
                server.watcher.add(includeDir)
                server.watcher.on('change', (file) => {
                    if (file.startsWith(includeDir)) {
                        server.ws.send({ type: 'full-reload' })
                    }
                })
            },
        },
        {
            name: 'html-generator',
            transformIndexHtml(html, _) {
                html = html.replaceAll(/{{ include '(.*?)' '(.*?)' }}/g, (_, metadata: string, filepath: string) => {
                    // Transpile typescript and bundle dependencies
                    if (filepath.endsWith('.ts')) {
                        const result = buildSync({
                            entryPoints: [join(ROOT, filepath)],
                            bundle: true,
                            write: false,
                            format: 'esm',
                            target: 'es2023',
                        })
                        return `<script>window.addEventListener('load',()=>{${result.outputFiles[0].text};})</script>`
                    }

                    // Embed as JSON string
                    if (filepath.endsWith('.json')) {
                        const content = readFileSync(join(ROOT, filepath), 'utf8')
                        return `<script type="application/json" id="${metadata}">\n${content}</script>`
                    }

                    // Embed as Base64 URI
                    if (['.png', '.gif'].find((ext) => filepath.endsWith(ext))) {
                        const content = readFileSync(join(ROOT, filepath), 'base64')
                        return `data:${metadata};base64,${content}`
                    }

                    // Generic tag generator
                    const content = readFileSync(join(ROOT, filepath), 'utf8')
                    return `<${metadata}>\n${content}</${metadata}>`
                })

                return minify(html, {
                    collapseWhitespace: true,
                    removeComments: true,
                    minifyCSS: true,
                    minifyJS: true,
                })
            },
        },
    ],
})
