package fabrik.simulator.pic16f84;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

import fabrik.simulator.pic16f84.interfaces.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;


class CommandsTests {
    PICComponentLocator picComponents;

    public CommandsTests() {}

    @BeforeEach
    void resetComponents() {
        picComponents = new PICComponentLocator();
    }

    @Test
    @DisplayName("Execution Time wird korrekt addiert")
    void executionTimeIsAddedCorrectly() {
        TimerInterface timerMock = mock(TimerInterface.class);
        picComponents.registerComponent(TimerInterface.class, timerMock);

        EEPROMInterface eepromMock = mock(EEPROMInterface.class);
        picComponents.registerComponent(EEPROMInterface.class, eepromMock);

        Commands commands = new Commands();
        picComponents.registerComponent(CommandInterface.class, commands);
        picComponents.initAll();


        commands.addExecutionTime(5);


        assertEquals(5, commands.getTotalExecutionTime());
    }

    @Test
    @DisplayName("Execution Time wird korrekt zurückgesetzt")
    void executionTimeResetWorks() {
        TimerInterface timerMock = mock(TimerInterface.class);
        picComponents.registerComponent(TimerInterface.class, timerMock);

        EEPROMInterface eepromMock = mock(EEPROMInterface.class);
        picComponents.registerComponent(EEPROMInterface.class, eepromMock);

        Commands commands = new Commands();
        picComponents.registerComponent(CommandInterface.class, commands);
        picComponents.initAll();


        commands.addExecutionTime(5);
        commands.resetTotalExecutionTime();


        assertEquals(0, commands.getTotalExecutionTime());
    }

    @Test
    @DisplayName("Execution Time Faktor wird berücksichtigt")
    void executionTimeMultiplierIsUsed() {
        TimerInterface timerMock = mock(TimerInterface.class);
        picComponents.registerComponent(TimerInterface.class, timerMock);

        EEPROMInterface eepromMock = mock(EEPROMInterface.class);
        picComponents.registerComponent(EEPROMInterface.class, eepromMock);

        Commands commands = new Commands();
        picComponents.registerComponent(CommandInterface.class, commands);
        picComponents.initAll();

        commands.addExecutionTime(5);
        commands.setExecutionTimeMultiplier("100 HZ");

        assertEquals(5 * 40, commands.getTotalExecutionTime());
    }

    @Test
    @DisplayName("Decode mit ungültigem Opcode wirft keine Exception")
    void decodeInvalidOpcodeDoesNotCrash() {
        CommandInterface commands = new Commands();

        assertDoesNotThrow(() -> commands.decode(1));
    }
}
