package io.openems.edge.io.test;

import io.openems.common.channel.AccessMode;
import io.openems.common.types.OpenemsType;
import io.openems.edge.common.channel.BooleanReadChannel;
import io.openems.edge.common.channel.BooleanWriteChannel;
import io.openems.edge.common.channel.ChannelId.ChannelIdImpl;
import io.openems.edge.common.channel.Doc;
import io.openems.edge.common.component.OpenemsComponent;
import io.openems.edge.common.test.AbstractDummyOpenemsComponent;
import io.openems.edge.io.api.DigitalInput;
import io.openems.edge.io.api.DigitalOutput;

/**
 * Provides a simple, simulated Digital Input/Output component that can be used
 * together with the OpenEMS Component test framework.
 */
public class DummyCustomInputOutput extends AbstractDummyOpenemsComponent<DummyCustomInputOutput>
		implements DigitalInput, DigitalOutput {

	private final BooleanWriteChannel[] ioChannels;

	public DummyCustomInputOutput(String id) {
		this(id, "INPUT_OUTPUT", 0, 10);
	}

	public DummyCustomInputOutput(String id, String prefix, int start, int numberOfIOs) {
		super(id, //
				OpenemsComponent.ChannelId.values(), //
				DigitalInput.ChannelId.values(), //
				DigitalOutput.ChannelId.values() //
		);

		this.ioChannels = new BooleanWriteChannel[numberOfIOs];
		for (int i = 0; i < numberOfIOs; i++) {
			this.ioChannels[i] = (BooleanWriteChannel) this
					.addChannel(new ChannelIdImpl(prefix + "_" + (i + start), Doc.of(OpenemsType.BOOLEAN).//
							accessMode(AccessMode.READ_WRITE)));
		}
	}

	public DummyCustomInputOutput(String id, String prefix, String suffix, int start, int numberOfIos,
			int numberOfModules) {
		super(id, //
				OpenemsComponent.ChannelId.values(), //
				DigitalInput.ChannelId.values(), //
				DigitalOutput.ChannelId.values() //
		);

		this.ioChannels = new BooleanWriteChannel[numberOfIos * numberOfModules];
		for (int j = 0; j < numberOfModules; j++) {
			for (int i = 0; i < numberOfIos; i++) {
				this.ioChannels[j * numberOfIos + i] = (BooleanWriteChannel) this.addChannel(
						new ChannelIdImpl(prefix + j + "_" + suffix + (i + start), Doc.of(OpenemsType.BOOLEAN).//
								accessMode(AccessMode.READ_WRITE)));
			}
		}
	}

	@Override
	protected DummyCustomInputOutput self() {
		return this;
	}

	@Override
	public BooleanWriteChannel[] digitalOutputChannels() {
		return this.ioChannels;
	}

	@Override
	public BooleanReadChannel[] digitalInputChannels() {
		return this.ioChannels;
	}

}
