package online.undergroundapps.appstore;

import android.content.Context;
import android.content.SharedPreferences;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public final class CatalogStore {
    public static final String REMOTE_URL = "https://install.undergroundapps.online/data/native-apps.json";
    private static final String PREFS = "underground_store";
    private static final String KEY_CATALOG = "cached_catalog";
    private static final String KEY_LAST_UPDATED = "last_updated";

    private CatalogStore() {}

    public static JSONObject load(Context context) throws Exception {
        SharedPreferences p = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
        String cached = p.getString(KEY_CATALOG, "");
        if (cached != null && !cached.trim().isEmpty()) {
            try {
                JSONObject o = new JSONObject(cached);
                validate(o);
                return o;
            } catch (Exception ignored) {
                p.edit().remove(KEY_CATALOG).apply();
            }
        }
        return loadBundled(context);
    }

    public static JSONObject loadBundled(Context context) throws Exception {
        try (InputStream in = context.getAssets().open("catalog.json")) {
            JSONObject o = new JSONObject(readFully(in));
            validate(o);
            return o;
        }
    }

    public static List<AppEntry> apps(JSONObject root) {
        List<AppEntry> list = new ArrayList<>();
        JSONArray a = root.optJSONArray("apps");
        if (a == null) return list;
        for (int i = 0; i < a.length(); i++) {
            JSONObject o = a.optJSONObject(i);
            if (o != null) list.add(AppEntry.fromJson(o));
        }
        return list;
    }

    public static void saveRemote(Context context, String json) throws Exception {
        JSONObject o = new JSONObject(json);
        validate(o);
        context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
                .edit()
                .putString(KEY_CATALOG, o.toString())
                .putLong(KEY_LAST_UPDATED, System.currentTimeMillis())
                .apply();
    }

    public static void clearRemote(Context context) {
        context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
                .edit().remove(KEY_CATALOG).remove(KEY_LAST_UPDATED).apply();
    }

    public static long lastUpdated(Context context) {
        return context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
                .getLong(KEY_LAST_UPDATED, 0L);
    }

    public static void validate(JSONObject root) throws Exception {
        JSONArray apps = root.optJSONArray("apps");
        if (apps == null || apps.length() < 1) throw new Exception("Catalog contains no apps");
        for (int i = 0; i < apps.length(); i++) {
            JSONObject app = apps.optJSONObject(i);
            if (app == null || app.optString("id", "").trim().isEmpty() || app.optString("name", "").trim().isEmpty()) {
                throw new Exception("Catalog has an invalid app entry");
            }
            String remote = app.optString("apkUrl", "");
            if (!remote.isEmpty() && !remote.startsWith("https://")) {
                throw new Exception("Remote APK URLs must use HTTPS");
            }
            String icon = app.optString("iconUrl", "");
            if (!icon.isEmpty() && !icon.startsWith("https://")) {
                throw new Exception("Remote icon URLs must use HTTPS");
            }
        }
    }

    public static String readFully(InputStream in) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
        StringBuilder b = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) b.append(line).append('\n');
        return b.toString();
    }
}
