package com.livingworld.testing;

import com.livingworld.data.serialization.PersistenceReader;
import com.livingworld.data.serialization.PersistenceWriter;
import com.livingworld.events.LivingWorldEvent;
import com.livingworld.modules.ModuleContext;
import com.livingworld.modules.ModuleMetadata;
import com.livingworld.modules.ModuleUpdateResult;
import com.livingworld.modules.RegionUpdateContext;
import com.livingworld.modules.ServerContext;
import com.livingworld.modules.SimulationModule;
import com.livingworld.regions.Region;
import java.util.List;

/**
 * Deterministic module used to exercise the simulation engine in tests.
 */
public final class TestSimulationModule implements SimulationModule {

    public static final String MODULE_ID = "test";

    private static final ModuleMetadata METADATA = new ModuleMetadata(
            MODULE_ID,
            "Test Simulation Module",
            "1.0.0",
            "Deterministic module for engine tests.",
            "1",
            List.of(),
            List.of(),
            true,
            true,
            false);

    private boolean initialized;
    private int updateCount;

    @Override
    public String getModuleId() {
        return MODULE_ID;
    }

    @Override
    public ModuleMetadata getMetadata() {
        return METADATA;
    }

    @Override
    public void initialize(ModuleContext context) {
        if (context == null) {
            throw new IllegalArgumentException("context must not be null");
        }
        initialized = true;
    }

    @Override
    public void onServerStarted(ServerContext context) {
        // No server resources are needed by the test module.
    }

    @Override
    public void createDefaultRegionData(Region region) {
        // The test module keeps deterministic counters outside region data.
    }

    @Override
    public ModuleUpdateResult updateRegion(RegionUpdateContext context) {
        if (context == null) {
            throw new IllegalArgumentException("context must not be null");
        }
        updateCount++;
        return updateCount % 10 == 0
                ? ModuleUpdateResult.changed()
                : ModuleUpdateResult.noChange();
    }

    @Override
    public void onLivingWorldEvent(LivingWorldEvent event) {
        // The test module does not consume events.
    }

    @Override
    public void saveModuleData(PersistenceWriter writer) {
        // The counter is intentionally transient test state.
    }

    @Override
    public void loadModuleData(PersistenceReader reader) {
        // The counter is intentionally transient test state.
    }

    @Override
    public void shutdown() {
        // No resources to release.
    }

    public boolean isInitialized() {
        return initialized;
    }

    public int getUpdateCount() {
        return updateCount;
    }
}
