package cgeo.geocaching.models;

import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.storage.DataStore;
import cgeo.geocaching.utils.formulas.VariableList;

import androidx.annotation.NonNull;
import androidx.core.util.Consumer;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Stores cache variables including view state (e.g. ordering).
 * This class handles persistence (load-from/store-to DB), allows for reset and change listeners.
 */
public class CacheVariableList extends VariableList {

    private final String geocode;

    private Map<Object, Consumer<String>> changeListener = new HashMap<>();

    public CacheVariableList(@NonNull final String geocode) {
        this.geocode = geocode;
        loadState();
    }

    public String getGeocode() {
        return geocode;
    }

    public void addChangeListener(final Object key, final Consumer<String> callback) {
        this.changeListener.put(key, callback);
    }

    public void removeChangeListener(final Object key) {
        this.changeListener.remove(key);
    }

    private void callCallbacks() {
        for (Consumer<String> c : this.changeListener.values()) {
            c.accept(this.geocode);
        }
    }

    private void loadState() {
        final List<VariableList.VariableEntry> rows = DataStore.loadVariables(this.geocode);
        this.setEntries(rows);
    }

    public void reloadLastSavedState() {
        if (!this.wasModified()) {
            return;
        }

        this.loadState();
        this.recalculateWaypoints();
        this.callCallbacks();
    }

    public void saveState() {
        if (!this.wasModified()) {
            return;
        }
        final List<VariableList.VariableEntry> rows = this.getEntries();
        DataStore.upsertVariables(this.geocode, rows);

        this.recalculateWaypoints();
        this.resetModified();
        this.callCallbacks();
    }

    private boolean recalculateWaypoints() {

        boolean hasCalculatedWp = false;
        final Geocache cache = DataStore.loadCache(this.geocode, LoadFlags.LOAD_CACHE_OR_DB);
        if (cache != null) {
            for (Waypoint wp : cache.getWaypoints()) {
                if (wp.isCalculated()) {
                    hasCalculatedWp = true;
                    final CalculatedCoordinate cc = CalculatedCoordinate.createFromConfig(wp.getCalcStateJson());
                    final Geopoint gp = cc.calculateGeopoint(this::getValue);
                    wp.setCoords(gp);
                }
            }
            if (hasCalculatedWp) {
                DataStore.saveWaypoints(cache);
            }
        }
        return hasCalculatedWp;
    }
}

@@ -246,16 +246,53 @@
 onNull;%0A
+import androidx.annotation.Nullable;%0A
 import a
@@ -337,23 +337,78 @@
 va.util.
-HashMap
+Collection;%0Aimport java.util.HashMap;%0Aimport java.util.HashSet
 ;%0Aimport
@@ -445,16 +445,38 @@
 til.Map;
+%0Aimport java.util.Set;
 %0A%0A/**%0A *
@@ -728,17 +728,16 @@
 eocode;%0A
-%0A
     priv
@@ -740,16 +740,22 @@
 private 
+final 
 Map%3CObje
@@ -2087,32 +2087,879 @@
 backs();%0A    %7D%0A%0A
+    @Override%0A    public void tidyUp(@Nullable final Collection%3CString%3E varsNeeded) %7B%0A        final Set%3CString%3E varsNeededReal = new HashSet%3C%3E();%0A        if (varsNeeded != null) %7B%0A            varsNeededReal.addAll(varsNeeded);%0A        %7D%0A        addAllWaypointNeededVars(varsNeededReal);%0A        super.tidyUp(varsNeededReal);%0A    %7D%0A%0A    private void addAllWaypointNeededVars(final Set%3CString%3E neededVars) %7B%0A        final Geocache cache = DataStore.loadCache(this.geocode, LoadFlags.LOAD_CACHE_OR_DB);%0A        if (cache != null) %7B%0A            for (Waypoint wp : cache.getWaypoints()) %7B%0A                if (wp.isCalculated()) %7B%0A                    final CalculatedCoordinate cc = CalculatedCoordinate.createFromConfig(wp.getCalcStateJson());%0A                    neededVars.addAll(cc.getNeededVars());%0A                %7D%0A            %7D%0A        %7D%0A    %7D%0A%0A
     private bool
@@ -3699,10 +3699,11 @@
 ;%0A    %7D%0A
+ 
 %7D%0A

fix #12535: keep used vars on tidy up (#12582)