// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
// SPDX-License-Identifier: GPL-3.0-or-later

package space.rcmd.android.sizzle.io

import java.io.File

/**
 * The on-device project library. Songs are stored as **full-fidelity** projects
 * ([ProjectIo] text: patterns, arrangement, mixer, FX and instrument settings) so
 * saving/loading round-trips the whole song — unlike the desktop-compatible `.sng`
 * ([SngFormat]), which carries only the musical data and is used purely for
 * export/import interchange (see [writeExport]).
 *
 *     <baseDir>/My Tune.szg      ← full project (what Save/Load use)
 *     <baseDir>/.export/…​.sng    ← transient .sng written for sharing
 *
 * The library only moves text around; serialization lives in [ProjectIo] /
 * [SngFormat].
 */
class SongLibrary(private val baseDir: File) {

    /** Names (without extension) of the stored full projects, alphabetically. */
    fun list(): List<String> =
        baseDir.listFiles { f -> f.isFile && f.name.endsWith(EXT) }
            ?.map { it.name.removeSuffix(EXT) }
            ?.sorted()
            ?: emptyList()

    fun file(name: String): File = File(baseDir.apply { mkdirs() }, sanitize(name) + EXT)

    /** Write [text] as the named full project. Returns the written file. */
    fun save(name: String, text: String): File {
        val f = file(name)
        f.writeText(text)
        return f
    }

    /** Read the named full project's text, or null if it doesn't exist. */
    fun load(name: String): String? = file(name).takeIf { it.exists() }?.readText()

    /** Delete the named full project. Returns true if it existed. */
    fun delete(name: String): Boolean = file(name).let { if (it.exists()) it.delete() else false }

    /**
     * Write a one-off `.sng` export (desktop interchange) to a shareable sub-dir
     * and return the file. Kept separate from the [EXT] library files so it never
     * shows up in the project list.
     */
    fun writeExport(name: String, sngText: String): File {
        val dir = File(baseDir, EXPORT_DIR).apply { mkdirs() }
        val f = File(dir, sanitize(name) + ".sng")
        f.writeText(sngText)
        return f
    }

    /** Keep names safe as file names while staying human-readable. */
    private fun sanitize(name: String): String =
        name.trim().replace(Regex("[^A-Za-z0-9._ -]"), "_").ifBlank { "song" }

    private companion object {
        const val EXT = ".szg"        // full project (ProjectIo)
        const val EXPORT_DIR = ".export"
    }
}
