package click.kamil.examples.statemachine.layered.dispatch;

import click.kamil.examples.statemachine.layered.command.DomainCommand;
import click.kamil.examples.statemachine.layered.document.DocumentState;
import click.kamil.examples.statemachine.layered.document.DocumentTransitionEvent;
import click.kamil.examples.statemachine.layered.order.OrderState;
import click.kamil.examples.statemachine.layered.order.OrderTransitionEvent;
import click.kamil.examples.statemachine.layered.order.PayRichOrderEvent;
import click.kamil.examples.statemachine.layered.order.ShipRichOrderEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.stereotype.Service;

@Service
public class CentralEventDispatcher {

    private final StateMachineFactory<OrderState, OrderTransitionEvent> orderStateMachineFactory;
    private final StateMachineFactory<DocumentState, DocumentTransitionEvent> documentStateMachineFactory;

    @Autowired
    public CentralEventDispatcher(
            StateMachineFactory<OrderState, OrderTransitionEvent> orderStateMachineFactory,
            StateMachineFactory<DocumentState, DocumentTransitionEvent> documentStateMachineFactory) {
        this.orderStateMachineFactory = orderStateMachineFactory;
        this.documentStateMachineFactory = documentStateMachineFactory;
    }

    public void dispatch(DomainCommand command) {
        switch (command) {
            case ORDER_PAY -> orderPay();
            case ORDER_SHIP -> orderShip();
            case ORDER_CANCEL -> orderCancel();
            case DOCUMENT_SUBMIT -> documentSubmit();
            case DOCUMENT_APPROVE -> documentApprove();
            case DOCUMENT_REJECT -> documentReject();
        }
    }

    public void orderPay() {
        sendOrderEvent(OrderTransitionEvent.PAY);
    }

    public void orderShip() {
        sendOrderEvent(OrderTransitionEvent.SHIP);
    }

    public void orderCancel() {
        sendOrderEvent(OrderTransitionEvent.CANCEL);
    }

    public void orderPayViaRichEvent(PayRichOrderEvent event) {
        sendOrderEvent(event.getType());
    }

    public void orderShipViaRichEvent(ShipRichOrderEvent event) {
        sendOrderEvent(event.getType());
    }

    public void documentSubmit() {
        sendDocumentEvent(DocumentTransitionEvent.SUBMIT);
    }

    public void documentApprove() {
        sendDocumentEvent(DocumentTransitionEvent.APPROVE);
    }

    public void documentReject() {
        sendDocumentEvent(DocumentTransitionEvent.REJECT);
    }

    private void sendOrderEvent(OrderTransitionEvent event) {
        StateMachine<OrderState, OrderTransitionEvent> machine = orderStateMachineFactory.getStateMachine();
        machine.start();
        machine.sendEvent(event);
    }

    private void sendDocumentEvent(DocumentTransitionEvent event) {
        StateMachine<DocumentState, DocumentTransitionEvent> machine = documentStateMachineFactory.getStateMachine();
        machine.start();
        machine.sendEvent(event);
    }
}
