package de.tudresden.inf.st.rosjava_rag_connector.signal_connector_module;

import de.tudresden.inf.st.pnml.jastadd.model.*;
import de.tudresden.inf.st.service.PetriNetInitService;
import org.apache.commons.logging.Log;
import org.ros.message.MessageListener;
import org.ros.namespace.GraphName;
import org.ros.node.AbstractNodeMain;
import org.ros.node.ConnectedNode;
import org.ros.node.Node;
import org.ros.node.topic.Publisher;
import org.ros.node.topic.Subscriber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import std_msgs.String;

import java.util.List;
import java.util.function.Consumer;

public class SignalConnector extends AbstractNodeMain {

    private static final Logger logger = LoggerFactory.getLogger(SignalConnector.class);
    private List<Marking> markedGraphs = null;
    private JavaHandler jh = JavaHandler.getInstance();

    @Override
    public GraphName getDefaultNodeName() {
        return GraphName.of("pn/signalconnector");
    }

    @Override
    public void onError(Node node, Throwable throwable) {
        logger.error("[SIGNALCONNECTOR] An error occurred: " + throwable.getLocalizedMessage());
    }

    @Override
    public void onStart(final ConnectedNode connectedNode) {

        // TODO replace path with config-parameter
        markedGraphs = PetriNetInitService.initMarkedGraphs("src/rosjava_catkin_package_a/my_pub_sub_tutorial/src/main/resources/minimal.pnml");

        for(Marking markedGraph : markedGraphs){

            for(Place place : markedGraph.getPetriNet().allPlaces()){
                OutputSignalPlace osp = place.asOutputSignalPlace();
                for(OutputSignalBinding osBinding : osp.getOutputSignalBindingList()){

                    final Publisher<String> publisher = connectedNode.newPublisher("/outputsignal/" + osBinding.getId(), std_msgs.String._TYPE);

                    jh.registerCallback("/outputsignal/" + osBinding.getId(), new Consumer<byte[]>() {
                        @Override
                        public void accept(byte[] bytes) {
                            std_msgs.String str = publisher.newMessage();
                            str.setData(new java.lang.String(bytes));
                            publisher.publish(str);
                        }
                    });
                }
            }

            for(Transition transition : markedGraph.getPetriNet().allTransitions()){
                InputSignalTransition ist = transition.asInputSignalTransition();
                for(InputSignalBinding isBinding : ist.getInputSignalBindingList()){

                    final Subscriber<String> subscriber = connectedNode.newSubscriber("/inputsignal/" /*+ isBinding.getId()*/, std_msgs.String._TYPE);

                    subscriber.addMessageListener(new MessageListener<String>() {
                        @Override
                        public void onNewMessage(std_msgs.String message) {
                    //        jh.push("/inputsignal/" + isBinding.getId(), message.getData().getBytes());
                        }
                    }, 1000);
                }
            }
        }
    }
}
