/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.openflow.drivers;

import org.onosproject.openflow.controller.Dpid;
import org.onosproject.openflow.controller.RoleState;
import org.onosproject.openflow.controller.OpenFlowSwitch.TableType;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFGroupFeaturesStatsReply;
import org.projectfloodlight.openflow.protocol.OFMatchV3;
import org.projectfloodlight.openflow.protocol.OFOxmList;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFBufferId;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.util.HexString;

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

public class OFSwitchImplSpringOpenTTP extends AbstractOpenFlowSwitch {

    private OFFactory factory;

    private final AtomicBoolean driverHandshakeComplete;
    private AtomicBoolean haltStateMachine;

    private DriverState driverState;

    /* Default table ID - compatible with CpqD switch */
    private static final int TABLE_VLAN = 0;
    private static final int TABLE_TMAC = 1;
    private static final int TABLE_IPV4_UNICAST = 2;
    private static final int TABLE_MPLS = 3;
    private static final int TABLE_ACL = 5;

    private static final long TEST_FLOW_REMOVED_MASK = 0xf;
    private static final long TEST_PACKET_IN_MASK = 0x7;
    private static final long TEST_PORT_STATUS_MASK = 0x7;

    private static final int OFPCML_NO_BUFFER = 0xffff;

    private long barrierXidToWaitFor = -1;

    /* Set the default values. These variables will get
     * overwritten based on the switch vendor type
     */
    protected int vlanTableId = TABLE_VLAN;
    protected int tmacTableId = TABLE_TMAC;
    protected int ipv4UnicastTableId = TABLE_IPV4_UNICAST;
    protected int mplsTableId = TABLE_MPLS;
    protected int aclTableId = TABLE_ACL;

    /* priority values for OF message */
    private static final short MAX_PRIORITY = (short) 0xffff;
    private static final short PRIORITY_MULTIPLIER = (short) 2046;
    private static final short MIN_PRIORITY = 0x0;


    protected OFSwitchImplSpringOpenTTP(Dpid dpid, OFDescStatsReply desc) {
        super(dpid);
        driverHandshakeComplete = new AtomicBoolean(false);
        haltStateMachine = new AtomicBoolean(false);
        driverState = DriverState.INIT;
        setSwitchDescription(desc);
    }


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

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

    @Override
    public void startDriverHandshake() {
        log.debug("Starting driver handshake for sw {}", getStringId());
        if (startDriverHandshakeCalled) {
            throw new SwitchDriverSubHandshakeAlreadyStarted();
        }
        startDriverHandshakeCalled = true;
        factory = this.factory();

        try {
            nextDriverState();
        } catch (IOException e) {
            log.error("Error {} during driver handshake for sw {}", e.getCause(),
                    getStringId());
        }
    }

    @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);
        }
        try {
            processOFMessage(m);
        } catch (IOException e) {
            log.error("Error generated when processing OFMessage {}", e.getCause());
        }
    }

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

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

    @Override
    public void transformAndSendMsg(OFMessage m, TableType tableType) {

        if (m.getType() == OFType.FLOW_MOD) {
            OFFlowMod flowMod = (OFFlowMod) m;
            OFFlowMod.Builder builder = flowMod.createBuilder();
            builder.setTableId(getTableId(tableType));
            OFFlowMod newFlowMod = builder.build();
            if (role == RoleState.MASTER) {
                this.write(newFlowMod);
            }
        } else {
            if (role == RoleState.MASTER) {
                this.write(m);
            }
        }
    }

    /*
     * Driver handshake state machine
     */

    enum DriverState {
        INIT,
        SET_TABLE_MISS_ENTRIES,
        SET_TABLE_VLAN_TMAC,
        AUDIT_GROUPS,
        SET_GROUPS,
        VERIFY_GROUPS,
        SET_ADJACENCY_LABELS,
        EXIT
    }

    protected void nextDriverState() throws IOException {
        DriverState currentState = driverState;
        if (haltStateMachine.get()) {
            return;
        }
        switch (currentState) {
            case INIT:
                driverState = DriverState.SET_TABLE_MISS_ENTRIES;
                setTableMissEntries();
                sendHandshakeBarrier();
                break;
            case SET_TABLE_MISS_ENTRIES:
                driverState = DriverState.SET_TABLE_VLAN_TMAC;
                /* TODO: read network configuration
                boolean isConfigured = getNetworkConfig();
                if (!isConfigured) {
                    return; // this will result in a handshake timeout
                }
                */
                populateTableVlan();
                populateTableTMac();
                sendHandshakeBarrier();
                break;
            case SET_TABLE_VLAN_TMAC:
                driverState = DriverState.EXIT;
                driverHandshakeComplete.set(true);
                log.debug("Driver handshake is complete");
                break;
            case EXIT:
            default:
                driverState = DriverState.EXIT;
                log.error("Driver handshake has exited for sw: {}", getStringId());
        }
    }

    private void processStatsReply(OFStatsReply sr) {
        switch (sr.getStatsType()) {
            case AGGREGATE:
                break;
            case DESC:
                break;
            case EXPERIMENTER:
                break;
            case FLOW:
                break;
            case GROUP_DESC:
                processGroupDesc((OFGroupDescStatsReply) sr);
                break;
            case GROUP_FEATURES:
                processGroupFeatures((OFGroupFeaturesStatsReply) sr);
                break;
            case METER_CONFIG:
                break;
            case METER_FEATURES:
                break;
            case PORT_DESC:
                break;
            case TABLE_FEATURES:
                break;
            default:
                break;

        }
    }

    private void processOFMessage(OFMessage m) throws IOException {
        switch (m.getType()) {
            case BARRIER_REPLY:
                processBarrierReply(m);
                break;

            case ERROR:
                processErrorMessage(m);
                break;

            case GET_ASYNC_REPLY:
                OFAsyncGetReply asrep = (OFAsyncGetReply) m;
                decodeAsyncGetReply(asrep);
                break;

            case PACKET_IN:
                // not ready to handle packet-ins
                break;

            case QUEUE_GET_CONFIG_REPLY:
                // not doing queue config yet
                break;

            case STATS_REPLY:
                processStatsReply((OFStatsReply) m);
                break;

            case ROLE_REPLY: // channelHandler should handle this
            case PORT_STATUS: // channelHandler should handle this
            case FEATURES_REPLY: // don't care
            case FLOW_REMOVED: // don't care
            default:
                log.debug("Received message {} during switch-driver subhandshake "
                        + "from switch {} ... Ignoring message", m, getStringId());
        }
    }

    private void processBarrierReply(OFMessage m) throws IOException {
        if (m.getXid() == barrierXidToWaitFor) {
            // Driver state-machine progresses to the next state.
            // If Barrier messages is not received, then eventually
            // the ChannelHandler state machine will timeout, and the switch
            // will be disconnected.
            nextDriverState();
        } else {
            log.error("Received incorrect barrier-message xid {} (expected: {}) in "
                            + "switch-driver state {} for switch {}", m, barrierXidToWaitFor,
                    driverState, getStringId());
        }
    }

    private void processErrorMessage(OFMessage m) {
        log.error("Switch {} Error {} in DriverState", getStringId(),
                (OFErrorMsg) m, driverState);
    }

    private void processGroupFeatures(OFGroupFeaturesStatsReply gfsr) {
        log.info("Sw: {} Group Features {}", getStringId(), gfsr);
    }

    private void processGroupDesc(OFGroupDescStatsReply gdsr) {
        log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
    }

    /*
     * Utility functions
     */

    private void decodeAsyncGetReply(OFAsyncGetReply rep) {
        long frm = rep.getFlowRemovedMaskEqualMaster();
        //long frs = rep.getFlowRemovedMaskSlave();
        long pim = rep.getPacketInMaskEqualMaster();
        //long pis = rep.getPacketInMaskSlave();
        long psm = rep.getPortStatusMaskEqualMaster();
        //long pss = rep.getPortStatusMaskSlave();

        if (role == RoleState.MASTER || role == RoleState.EQUAL) { // should separate
            log.info("FRM:{}", HexString.toHexString((frm & TEST_FLOW_REMOVED_MASK)));
            log.info("PIM:{}", HexString.toHexString((pim & TEST_PACKET_IN_MASK)));
            log.info("PSM:{}", HexString.toHexString((psm & TEST_PORT_STATUS_MASK)));
        }
    }

    protected void setTableMissEntries() throws IOException {
        // set all table-miss-entries
        populateTableMissEntry(vlanTableId, true, false, false, -1);
        populateTableMissEntry(tmacTableId, true, false, false, -1);
        populateTableMissEntry(ipv4UnicastTableId, false, true, true,
                aclTableId);
        populateTableMissEntry(mplsTableId, false, true, true,
                aclTableId);
        populateTableMissEntry(aclTableId, false, false, false, -1);
        log.debug("TableMissEntries are set");
    }

    /**
     * Adds a table-miss-entry to a pipeline table.
     * <p>
     * The table-miss-entry can be added with 'write-actions' or
     * 'apply-actions'. It can also add a 'goto-table' instruction. By default
     * if none of the booleans in the call are set, then the table-miss entry is
     * added with no instructions, which means that if a packet hits the
     * table-miss-entry, pipeline execution will stop, and the action set
     * associated with the packet will be executed.
     *
     * @param tableToAdd the table to where the table-miss-entry will be added
     * @param toControllerNow as an APPLY_ACTION instruction
     * @param toControllerWrite as a WRITE_ACTION instruction
     * @param toTable as a GOTO_TABLE instruction
     * @param tableToSend the table to send as per the GOTO_TABLE instruction it
     *        needs to be set if 'toTable' is true. Ignored of 'toTable' is
     *        false.
     */
    protected void populateTableMissEntry(int tableToAdd, boolean toControllerNow,
                                          boolean toControllerWrite,
                                          boolean toTable, int tableToSend) {
        OFOxmList oxmList = OFOxmList.EMPTY;
        OFMatchV3 match = factory.buildMatchV3()
                .setOxmList(oxmList)
                .build();
        OFAction outc = factory.actions()
                .buildOutput()
                .setPort(OFPort.CONTROLLER)
                .setMaxLen(OFPCML_NO_BUFFER)
                .build();
        List<OFInstruction> instructions = new ArrayList<OFInstruction>();
        if (toControllerNow) {
            // table-miss instruction to send to controller immediately
            OFInstruction instr = factory.instructions()
                    .buildApplyActions()
                    .setActions(Collections.singletonList(outc))
                    .build();
            instructions.add(instr);
        }

        if (toControllerWrite) {
            // table-miss instruction to write-action to send to controller
            // this will be executed whenever the action-set gets executed
            OFInstruction instr = factory.instructions()
                    .buildWriteActions()
                    .setActions(Collections.singletonList(outc))
                    .build();
            instructions.add(instr);
        }

        if (toTable) {
            // table-miss instruction to goto-table x
            OFInstruction instr = factory.instructions()
                    .gotoTable(TableId.of(tableToSend));
            instructions.add(instr);
        }

        if (!toControllerNow && !toControllerWrite && !toTable) {
            // table-miss has no instruction - at which point action-set will be
            // executed - if there is an action to output/group in the action
            // set
            // the packet will be sent there, otherwise it will be dropped.
            instructions = Collections.<OFInstruction>emptyList();
        }

        OFMessage tableMissEntry = factory.buildFlowAdd()
                .setTableId(TableId.of(tableToAdd))
                .setMatch(match) // match everything
                .setInstructions(instructions)
                .setPriority(MIN_PRIORITY)
                .setBufferId(OFBufferId.NO_BUFFER)
                .setIdleTimeout(0)
                .setHardTimeout(0)
                .setXid(getNextTransactionId())
                .build();
        write(tableMissEntry);
    }

    private void populateTableVlan() throws IOException {
        List<OFMessage> msglist = new ArrayList<OFMessage>();
        for (OFPortDesc p : getPorts()) {
            int pnum = p.getPortNo().getPortNumber();
            if (U32.of(pnum).compareTo(U32.of(OFPort.MAX.getPortNumber())) < 1) {
                OFOxmInPort oxp = factory.oxms().inPort(p.getPortNo());
                OFOxmVlanVid oxv = factory.oxms()
                        .vlanVid(OFVlanVidMatch.UNTAGGED);
                OFOxmList oxmList = OFOxmList.of(oxp, oxv);
                OFMatchV3 match = factory.buildMatchV3()
                        .setOxmList(oxmList).build();

                // TODO: match on vlan-tagged packets for vlans configured on
                // subnet ports and strip-vlan

                OFInstruction gotoTbl = factory.instructions().buildGotoTable()
                        .setTableId(TableId.of(tmacTableId)).build();
                List<OFInstruction> instructions = new ArrayList<OFInstruction>();
                instructions.add(gotoTbl);
                OFMessage flowEntry = factory.buildFlowAdd()
                        .setTableId(TableId.of(vlanTableId))
                        .setMatch(match)
                        .setInstructions(instructions)
                        .setPriority(1000) // does not matter - all rules
                                // exclusive
                        .setBufferId(OFBufferId.NO_BUFFER)
                        .setIdleTimeout(0)
                        .setHardTimeout(0)
                        .setXid(getNextTransactionId())
                        .build();
                msglist.add(flowEntry);
            }
        }
        write(msglist);
        log.debug("Adding {} port/vlan-rules in sw {}", msglist.size(), getStringId());
    }

    private void populateTableTMac() throws IOException {
        // match for router-mac and ip-packets
        OFOxmEthType oxe = factory.oxms().ethType(EthType.IPv4);

        /* TODO: need to read network config and need to allow only
         the packets with DMAC as the correspondent router MAC address
         Until network configuration is implemented, all packets are allowed

        OFOxmEthDst dmac = factory.oxms().ethDst(getRouterMacAddr());
        OFOxmList oxmListIp = OFOxmList.of(dmac, oxe);
        OFMatchV3 matchIp = factory.buildMatchV3()
                .setOxmList(oxmListIp).build();
        */
        OFOxmList oxmList = OFOxmList.EMPTY;
        OFMatchV3 matchIp = factory.buildMatchV3()
                .setOxmList(oxmList)
                .build();

        OFInstruction gotoTblIp = factory.instructions().buildGotoTable()
                .setTableId(TableId.of(ipv4UnicastTableId)).build();
        List<OFInstruction> instructionsIp = Collections.singletonList(gotoTblIp);
        OFMessage ipEntry = factory.buildFlowAdd()
                .setTableId(TableId.of(tmacTableId))
                .setMatch(matchIp)
                .setInstructions(instructionsIp)
                .setPriority(1000) // strict priority required lower than
                        // multicastMac
                .setBufferId(OFBufferId.NO_BUFFER)
                .setIdleTimeout(0)
                .setHardTimeout(0)
                .setXid(getNextTransactionId())
                .build();

        // match for router-mac and mpls packets
        OFOxmEthType oxmpls = factory.oxms().ethType(EthType.MPLS_UNICAST);
        /* TODO: need to read network config and need to allow only
         the packets with DMAC as the correspondent router MAC address
        OFOxmList oxmListMpls = OFOxmList.of(dmac, oxmpls);
        OFMatchV3 matchMpls = factory.buildMatchV3()
                .setOxmList(oxmListMpls).build();
        */
        OFOxmList oxmListMpls = OFOxmList.EMPTY;
        OFMatchV3 matchMpls = factory.buildMatchV3()
                .setOxmList(oxmList)
                .build();

        OFInstruction gotoTblMpls = factory.instructions().buildGotoTable()
                .setTableId(TableId.of(mplsTableId)).build();
        List<OFInstruction> instructionsMpls = Collections.singletonList(gotoTblMpls);
        OFMessage mplsEntry = factory.buildFlowAdd()
                .setTableId(TableId.of(tmacTableId))
                .setMatch(matchMpls)
                .setInstructions(instructionsMpls)
                .setPriority(1001) // strict priority required lower than
                        // multicastMac
                .setBufferId(OFBufferId.NO_BUFFER)
                .setIdleTimeout(0)
                .setHardTimeout(0)
                .setXid(getNextTransactionId())
                .build();

        log.debug("Adding termination-mac-rules in sw {}", getStringId());
        List<OFMessage> msglist = new ArrayList<OFMessage>(2);
        msglist.add(ipEntry);
        msglist.add(mplsEntry);
        write(msglist);
    }

    private MacAddress getRouterMacAddr() {
        // TODO: need to read network config : RouterIp
        return MacAddress.of("00:00:00:00:00:00");
    }

    private TableId getTableId(TableType tableType) {
        switch (tableType) {
            case IP:
                return TableId.of(ipv4UnicastTableId);
            case MPLS:
                return TableId.of(mplsTableId);
            case ACL:
                return TableId.of(aclTableId);
            default: {
                log.error("Table type {} is not supported in the driver", tableType);
                return TableId.NONE;
            }
        }
    }

    private void sendHandshakeBarrier() throws IOException {
        long xid = getNextTransactionId();
        barrierXidToWaitFor = xid;
        OFBarrierRequest br = factory()
                .buildBarrierRequest()
                .setXid(xid)
                .build();
        write(br);
    }

    @Override
    public TableType getTableType(TableId tid) {
        return TableType.NONE; // XXX this needs to be fixed
    }

}
