package io.openems.edge.app.api;

import static io.openems.edge.common.test.DummyUser.DUMMY_ADMIN;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import com.google.common.collect.ImmutableList;

import io.openems.common.utils.JsonUtils;
import io.openems.edge.core.appmanager.AppManagerTestBundle;
import io.openems.edge.core.appmanager.Apps;
import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance;
import io.openems.edge.core.appmanager.jsonrpc.DeleteAppInstance;

public class TestModbusTcpApiReadWrite {

	private AppManagerTestBundle appManagerTestBundle;
	private ModbusTcpApiReadOnly modbusTcpApiReadOnly;
	private ModbusTcpApiReadWrite modbusTcpApiReadWrite;

	@BeforeEach
	public void beforeEach() throws Exception {
		this.appManagerTestBundle = new AppManagerTestBundle(null, null, t -> {
			return ImmutableList.of(//
					this.modbusTcpApiReadOnly = Apps.modbusTcpApiReadOnly(t), //
					this.modbusTcpApiReadWrite = Apps.modbusTcpApiReadWrite(t) //
			);
		});
	}

	@Test
	public void testDeactivateReadOnly() throws Exception {
		// create ReadOnly app
		this.appManagerTestBundle.sut.handleAddAppInstanceRequest(DUMMY_ADMIN, new AddAppInstance.Request(
				this.modbusTcpApiReadOnly.getAppId(), "key", "alias", JsonUtils.buildJsonObject().build()));

		assertEquals(1, this.appManagerTestBundle.sut.getInstantiatedApps().size());

		// ACTIVE not set or true
		var readOnlyApp = this.appManagerTestBundle.sut.getInstantiatedApps().get(0);

		if (readOnlyApp.properties.has("ACTIVE")) {
			var isActive = readOnlyApp.properties.get("ACTIVE").getAsBoolean();
			assertTrue(isActive);
		}

		// create ReadWrite app
		this.appManagerTestBundle.sut.handleAddAppInstanceRequest(DUMMY_ADMIN,
				new AddAppInstance.Request(this.modbusTcpApiReadWrite.getAppId(), "key", "alias",
						JsonUtils.buildJsonObject() //
								.addProperty("API_TIMEOUT", 60) //
								.add("COMPONENT_IDS", JsonUtils.buildJsonArray() //
										.add("_sum") //
										.build()) //
								.build()));

		assertEquals(2, this.appManagerTestBundle.sut.getInstantiatedApps().size());

		final var readWriteApp = this.appManagerTestBundle.sut.getInstantiatedApps().get(0);

		// ACTIVE set and false
		readOnlyApp = this.appManagerTestBundle.sut.getInstantiatedApps().stream()
				.filter(app -> app.appId.contains("ReadOnly")).findAny().get();

		assertTrue(readOnlyApp.properties.has("ACTIVE"));
		var isActive = readOnlyApp.properties.get("ACTIVE").getAsBoolean();
		assertFalse(isActive);

		// remove ReadWrite to see if the ReadOnly gets activated
		this.appManagerTestBundle.sut.handleDeleteAppInstanceRequest(DUMMY_ADMIN,
				new DeleteAppInstance.Request(readWriteApp.instanceId));

		// ACTIVE not set or true
		readOnlyApp = this.appManagerTestBundle.sut.getInstantiatedApps().get(0);

		if (readOnlyApp.properties.has("ACTIVE")) {
			isActive = readOnlyApp.properties.get("ACTIVE").getAsBoolean();
			assertTrue(isActive);
		}
	}

}