package com.lemenzo.calculator.model import android.content.Context import org.json.JSONArray import org.json.JSONObject class HistoryStore(context: Context) { private val prefs = context.getSharedPreferences("history", Context.MODE_PRIVATE) data class Entry(val expression: String, val result: String, val timestamp: Long, val mode: String = "BASIC", val angleMode: String? = null, val programmerBase: String? = null, val wordSize: Int? = null) fun add(entry: Entry) { val items = all().toMutableList() items.removeAll { it.expression == entry.expression && it.result == entry.result && it.mode == entry.mode && it.programmerBase == entry.programmerBase && it.wordSize == entry.wordSize } items.add(0, entry.copy(timestamp = if (entry.timestamp > 0) entry.timestamp else System.currentTimeMillis())) save(items.take(MAX_ITEMS)) } fun all(): List { val raw = prefs.getString(KEY_V3, null) ?: prefs.getString(KEY_V2, null) ?: return emptyList() return runCatching { val array = JSONArray(raw) buildList { for (i in 0 until array.length()) { val o = array.getJSONObject(i) val legacyExpression = o.getString("expression") val legacy = Regex("^\\[(BIN|OCT|DEC|HEX)/(8|16|32|64)]\\s*(.*)$").find(legacyExpression) if (legacy != null && !o.has("mode")) add(Entry(legacy.groupValues[3], o.getString("result"), o.optLong("timestamp", 0L), "PROGRAMMER", programmerBase = legacy.groupValues[1], wordSize = legacy.groupValues[2].toInt())) else add(Entry(legacyExpression, o.getString("result"), o.optLong("timestamp", 0L), o.optString("mode", "BASIC"), o.optString("angleMode", "").takeIf { it.isNotBlank() && it != "null" }, o.optString("programmerBase", "").takeIf { it.isNotBlank() && it != "null" }, if (o.has("wordSize") && !o.isNull("wordSize")) o.optInt("wordSize") else null)) } } }.getOrDefault(emptyList()).also { if (prefs.contains(KEY_V2) && !prefs.contains(KEY_V3)) save(it) } } fun clear() { prefs.edit().remove(KEY_V3).remove(KEY_V2).apply() } private fun save(items: List) { val array = JSONArray() items.forEach { array.put(JSONObject().put("expression", it.expression).put("result", it.result).put("timestamp", it.timestamp).put("mode", it.mode).put("angleMode", it.angleMode ?: JSONObject.NULL).put("programmerBase", it.programmerBase ?: JSONObject.NULL).put("wordSize", it.wordSize ?: JSONObject.NULL)) } prefs.edit().putString(KEY_V3, array.toString()).remove(KEY_V2).apply() } private companion object { const val KEY_V3 = "ordered_items_v3"; const val KEY_V2 = "ordered_items_v2"; const val MAX_ITEMS = 200 } }