package org.onlab.onos.openflow.drivers.impl;

import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
import org.onlab.onos.openflow.controller.Dpid;
import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply;
import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFMatchV3;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFOxmList;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortOptical;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigid;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigtype;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigtypeBasic;
import org.projectfloodlight.openflow.types.CircuitSignalID;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.U8;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * LINC-OE Optical Emulator switch class.
 */
public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {

    private final AtomicBoolean driverHandshakeComplete;
    private long barrierXidToWaitFor = -1;

    private final Logger log =
            LoggerFactory.getLogger(OFOpticalSwitchImplLINC13.class);

    OFOpticalSwitchImplLINC13(Dpid dpid, OFDescStatsReply desc) {
        super(dpid);
        //setAttribute("optical", "true");
        driverHandshakeComplete = new AtomicBoolean(false);
        setSwitchDescription(desc);
    }

    @Override
    public String toString() {
        return "OFOpticalSwitchImplLINC13 [" + ((channel != null)
                ? channel.getRemoteAddress() : "?")
                + " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
    }

    @Override
    public void startDriverHandshake() {
        log.debug("Starting driver handshake for sw {}", getStringId());
        if (startDriverHandshakeCalled) {
            throw new SwitchDriverSubHandshakeAlreadyStarted();
        }
        startDriverHandshakeCalled = true;
        try {
            sendHandshakeOFExperimenterPortDescRequest();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean isDriverHandshakeComplete() {
        if (!startDriverHandshakeCalled) {
            throw new SwitchDriverSubHandshakeNotStarted();
        }
        return driverHandshakeComplete.get();
    }

    @Override
    public void processDriverHandshakeMessage(OFMessage m) {
        if (!startDriverHandshakeCalled) {
            throw new SwitchDriverSubHandshakeNotStarted();
        }
        if (driverHandshakeComplete.get()) {
            throw new SwitchDriverSubHandshakeCompleted(m);
        }

        switch (m.getType()) {
            case BARRIER_REPLY:
                if (m.getXid() == barrierXidToWaitFor) {
                    log.debug("LINC-OE Received barrier response");
                }
                break;
            case ERROR:
                log.error("Switch {} Error {}", getStringId(), (OFErrorMsg) m);
                break;
            case FEATURES_REPLY:
                break;
            case FLOW_REMOVED:
                break;
            case GET_ASYNC_REPLY:
                break;
            case PACKET_IN:
                break;
            case PORT_STATUS:
                break;
            case QUEUE_GET_CONFIG_REPLY:
                break;
            case ROLE_REPLY:
                break;
            case STATS_REPLY:
                log.debug("LINC-OE : Received stats reply message {}", m);
                processHandshakeOFExperimenterPortDescRequest(
                        (OFCircuitPortsReply) m);
                driverHandshakeComplete.set(true);
               /* try {
                    testMA();
                } catch (IOException e) {
                    e.printStackTrace();
                }*/
                break;
            default:
                log.debug("Received message {} during switch-driver " +
                                  "subhandshake " + "from switch {} ... " +
                                  "Ignoring message", m,
                          getStringId());

        }
    }


    private void processHandshakeOFExperimenterPortDescRequest(
            OFCircuitPortsReply sr) {
        Collection<OFPortOptical> entries = sr.getEntries();
        List<OFPortDesc> ofPortDescList = new ArrayList<>(entries.size());
        for (OFPortOptical entry : entries) {
            ofPortDescList.add(factory().buildPortDesc().
                    setPortNo(entry.getPortNo())
                                           .setConfig(entry.getConfig())
                                           .setState(entry.getState())
                                           .setHwAddr(entry.getHwAddr())
                                           .setName(entry.getName())
                                           .build());
        }
        setPortDescReply(factory().buildPortDescStatsReply().
                setEntries(ofPortDescList).build());
    }


    private void sendHandshakeOFExperimenterPortDescRequest() throws
            IOException {
        // send multi part message for port description for optical switches
        OFCircuitPortsRequest circuitPortsRequest = factory()
                .buildCircuitPortsRequest().setXid(getNextTransactionId())
                .build();
        log.debug("LINC-OE : Sending experimented circuit port stats " +
                          "message " +
                          "{}",
                  circuitPortsRequest.toString());
        channel.write(Collections.singletonList(circuitPortsRequest));
    }



    //todo for testing
    public static final U8 SIGNAL_TYPE = U8.of((short) 1);
    private void testMA() throws IOException {
        log.debug("LINC OE *** Testing MA ");
        short lambda = 100;
        if (getId() == 0x0000ffffffffff02L) {
            final int inport = 10;
            final int outport = 20;
            //Circuit signal id
            CircuitSignalID sigID = getSignalID(lambda);

            OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID);
            OFOxmOchSigtype fieldSigType = factory()
                    .oxms()
                    .ochSigtype(SIGNAL_TYPE);

            OFOxmOchSigidBasic ofOxmOchSigidBasic =
                    factory().oxms().ochSigidBasic(sigID);

            OFOxmOchSigtypeBasic ofOxmOchSigtypeBasic =
                    factory().oxms().ochSigtypeBasic(SIGNAL_TYPE);

            //Match Port
            OFOxmInPort fieldPort = factory().oxms()
                                                .inPort(OFPort.of(inport));
            OFMatchV3 matchPort =
                    factory()
                            .buildMatchV3().
                            setOxmList(OFOxmList.of(fieldPort,
                                                    fieldSigType,
                                                    fieldSigIDMatch)).build();


            // Set Action outport ,sigType and sigID
            List<OFAction> actionList = new ArrayList<>();
            OFAction actionOutPort =
                    factory().actions().output(OFPort.of(outport),
                                                  Short.MAX_VALUE);

            OFActionCircuit actionCircuit = factory()
                    .actions()
                    .circuit(ofOxmOchSigidBasic);
            OFActionCircuit setActionSigType = factory()
                    .actions()
                    .circuit(ofOxmOchSigtypeBasic);

            actionList.add(actionOutPort);
            actionList.add(setActionSigType);
            actionList.add(actionCircuit);

            OFInstruction instructionAction =
                    factory().instructions().buildApplyActions()
                                .setActions(actionList)
                                .build();
            List<OFInstruction> instructions =
                    Collections.singletonList(instructionAction);

            OFMessage opticalFlowEntry =
                    factory().buildFlowAdd()
                                .setMatch(matchPort)
                                .setInstructions(instructions)
                                .setXid(getNextTransactionId())
                                .build();
            log.debug("Adding optical flow in sw {}", getStringId());
            List<OFMessage> msglist = new ArrayList<>(1);
            msglist.add(opticalFlowEntry);
            write(msglist);
        } else if (getId() == 0x0000ffffffffff03L) {
            final int inport = 21;
            final int outport = 22;
            //Circuit signal id
            CircuitSignalID sigID = getSignalID(lambda);

            OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID);
            OFOxmOchSigtype fieldSigType = factory()
                    .oxms()
                    .ochSigtype(SIGNAL_TYPE);

            OFOxmOchSigidBasic ofOxmOchSigidBasic =
                    factory().oxms().ochSigidBasic(sigID);

            OFOxmOchSigtypeBasic ofOxmOchSigtypeBasic =
                    factory().oxms().ochSigtypeBasic(SIGNAL_TYPE);

            //Match Port,SigType,SigID
            OFOxmInPort fieldPort = factory()
                    .oxms()
                    .inPort(OFPort.of(inport));
            OFMatchV3 matchPort = factory()
                    .buildMatchV3()
                    .setOxmList(OFOxmList.of(fieldPort,
                                             fieldSigType,
                                             fieldSigIDMatch))
                    .build();

            // Set Action outport ,SigType, sigID
            List<OFAction> actionList = new ArrayList<>();
            OFAction actionOutPort =
                    factory().actions().output(OFPort.of(outport),
                                                  Short.MAX_VALUE);

            OFActionCircuit setActionSigType = factory()
                    .actions()
                    .circuit(ofOxmOchSigtypeBasic);
            OFActionCircuit actionCircuit = factory()
                    .actions()
                    .circuit(ofOxmOchSigidBasic);


            actionList.add(actionOutPort);
            actionList.add(setActionSigType);
            actionList.add(actionCircuit);

            OFInstruction instructionAction =
                    factory().instructions().buildApplyActions()
                                .setActions(actionList)
                                .build();
            List<OFInstruction> instructions =
                    Collections.singletonList(instructionAction);

            OFMessage opticalFlowEntry =
                    factory().buildFlowAdd()
                                 .setMatch(matchPort)
                                 .setInstructions(instructions)
                                 .setXid(getNextTransactionId())
                                 .build();
            log.debug("Adding optical flow in sw {}", getStringId());
            List<OFMessage> msglist = new ArrayList<>(1);
            msglist.add(opticalFlowEntry);
            write(msglist);

        } else if (getId() == 0x0000ffffffffff04L) {
            final int inport = 23;
            final int outport = 11;
            //Circuit signal id
            CircuitSignalID sigID = getSignalID(lambda);

            OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID);
            OFOxmOchSigtype fieldSigType = factory()
                    .oxms()
                    .ochSigtype(SIGNAL_TYPE);


            //Match Port, sig type and sig id
            OFOxmInPort fieldPort = factory()
                    .oxms()
                    .inPort(OFPort.of(inport));
            OFMatchV3 matchPort =
                    factory().buildMatchV3()
                                .setOxmList(OFOxmList.of(fieldPort,
                                                         fieldSigType,
                                                         fieldSigIDMatch))
                                .build();

            // Set Action outport
            List<OFAction> actionList = new ArrayList<>();
            OFAction actionOutPort =
                    factory().actions().output(OFPort.of(outport),
                                                  Short.MAX_VALUE);

            actionList.add(actionOutPort);

            OFInstruction instructionAction =
                    factory().instructions().buildApplyActions()
                                .setActions(actionList)
                                .build();
            List<OFInstruction> instructions =
                    Collections.singletonList(instructionAction);

            OFMessage opticalFlowEntry =
                    factory().buildFlowAdd()
                                 .setMatch(matchPort)
                                 .setInstructions(instructions)
                                 .setXid(getNextTransactionId())
                                 .build();
            log.debug("Adding optical flow in sw {}", getStringId());
            List<OFMessage> msglist = new ArrayList<>(1);
            msglist.add(opticalFlowEntry);
            write(msglist);
        }

    }

    // Todo remove - for testing purpose only
    private static CircuitSignalID getSignalID(short lambda) {
        byte myGrid = 1;
        byte myCs = 2;
        short myCn = lambda;
        short mySw = 1;

        CircuitSignalID signalID = new CircuitSignalID(myGrid,
                                                       myCs,
                                                       myCn,
                                                       mySw);
        return signalID;
    }

    @Override
    public void write(OFMessage msg) {
        this.channel.write(msg);
    }

    @Override
    public void write(List<OFMessage> msgs) {
        this.channel.write(msgs);
    }

    @Override
    public Boolean supportNxRole() {
        return false;
    }

}
