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

package space.rcmd.android.sizzle.io

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.first

/** The DataStore file backing app-level settings. */
private val Context.settingsDataStore: DataStore<Preferences> by preferencesDataStore(name = "app_settings")

/** App-level settings that persist across restarts (theme, recording, keyboard). */
data class AppSettings(
    val paletteName: String? = null,
    /** Persisted SAF tree URI for master-recording WAV output, or null if unset. */
    val recordDirUri: String? = null,
    /** FX-tail length (bars) captured after the sequencer stops. */
    val recordTailBars: Int = 2,
    /** Target MIDI channel for the on-screen keyboards (0 == empty channel). */
    val kbdChannel: Int = 0,
    /** Base octave for the on-screen keyboards. */
    val kbdOctave: Int = 3,
)

/**
 * Persists app-level UI/audio settings (the colour theme and the low-latency
 * engine toggle). Song/mixer/toolbox parameters live in the project and are
 * handled by [ProjectStore]; input bindings by
 * [space.rcmd.android.sizzle.input.BindingStore].
 *
 * Audio output/input *device* selection is intentionally not persisted: Android
 * device ids are session-scoped and don't identify the same hardware next launch.
 */
class SettingsStore(private val context: Context) {

    suspend fun load(): AppSettings {
        val prefs = context.settingsDataStore.data.first()
        return AppSettings(
            paletteName = prefs[PALETTE],
            recordDirUri = prefs[RECORD_DIR],
            recordTailBars = prefs[RECORD_TAIL] ?: 2,
            kbdChannel = prefs[KBD_CHANNEL] ?: 0,
            kbdOctave = prefs[KBD_OCTAVE] ?: 3,
        )
    }

    suspend fun save(paletteName: String) {
        context.settingsDataStore.edit { prefs ->
            prefs[PALETTE] = paletteName
        }
    }

    /** Persist the master-recording output folder and FX-tail length independently
     *  of the theme/engine settings (independent DataStore keys). */
    suspend fun saveRecording(dirUri: String?, tailBars: Int) {
        context.settingsDataStore.edit { prefs ->
            if (dirUri != null) prefs[RECORD_DIR] = dirUri
            prefs[RECORD_TAIL] = tailBars
        }
    }

    /** Persist the on-screen keyboard's MIDI channel + base octave. */
    suspend fun saveKeyboard(channel: Int, octave: Int) {
        context.settingsDataStore.edit { prefs ->
            prefs[KBD_CHANNEL] = channel
            prefs[KBD_OCTAVE] = octave
        }
    }

    private companion object {
        val PALETTE = stringPreferencesKey("palette")
        val RECORD_DIR = stringPreferencesKey("recordDirUri")
        val RECORD_TAIL = intPreferencesKey("recordTailBars")
        val KBD_CHANNEL = intPreferencesKey("kbdChannel")
        val KBD_OCTAVE = intPreferencesKey("kbdOctave")
    }
}
