/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.pi.demo.app.tor;

import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import org.onlab.packet.Ethernet;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.pi.model.PiPipelineInterpreter;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionId;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.net.pi.runtime.PiActionParamId;
import org.onosproject.net.pi.runtime.PiActionProfileId;
import org.onosproject.net.pi.runtime.PiCounterId;
import org.onosproject.net.pi.runtime.PiHeaderFieldId;
import org.onosproject.net.pi.runtime.PiPacketMetadata;
import org.onosproject.net.pi.runtime.PiPacketMetadataId;
import org.onosproject.net.pi.runtime.PiPacketOperation;
import org.onosproject.net.pi.runtime.PiTableId;

import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
import static org.onlab.util.ImmutableByteSequence.copyFrom;
import static org.onlab.util.ImmutableByteSequence.fit;
import static org.onosproject.net.PortNumber.CONTROLLER;
import static org.onosproject.net.PortNumber.FLOOD;
import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
import static org.onosproject.net.pi.runtime.PiPacketOperation.Type.PACKET_OUT;

/**
 * Implementation of a PiPipeline interpreter for tor.p4.
 */
public class TorInterpreter extends AbstractHandlerBehaviour implements PiPipelineInterpreter {

    private static final boolean PACKET_IO_ENABLED = true;

    //For this simple interpreter we need just the punt_table defined in punt.p4
    private static final String PUNT = "punt";
    private static final PiTableId PUNT_TABLE_ID = PiTableId.of(PUNT, "punt_table");
    private static final String SEND_TO_CPU = PUNT + ".set_queue_and_send_to_cpu";

    private static final String QUEUE_ID = "queue_id";

    private static final String EGRESS_PORT = "egress_physical_port";
    private static final String INGRESS_PORT = "ingress_physical_port";

    static final PiTableId L3_FILTER_TBL_ID = PiTableId.of("l3_fwd", "l3_routing_classifier_table");
    static final PiTableId L3_FWD_TBL_ID = PiTableId.of("l3_fwd", "l3_ipv4_override_table");
    static final PiActionId SET_NEXT_HOP_ACT_ID = PiActionId.of("l3_fwd.set_nexthop");
    static final PiActionParamId PORT_ACT_PRM_ID = PiActionParamId.of("port");
    static final PiActionParamId SMAC_ACT_PRM_ID = PiActionParamId.of("smac");
    static final PiActionParamId DMAC_ACT_PRM_ID = PiActionParamId.of("dmac");
    static final PiActionProfileId WCMP_ACT_PROF_ID = PiActionProfileId.of("l3_fwd.wcmp_action_profile");
    static final PiActionId NO_ACTION_ID = PiActionId.of("NoAction");

    // Set as per value in headers.p4 in packet_out_header
    private static final int PORT_FIELD_BITWIDTH = 9;

    private static final PiHeaderFieldId ETH_TYPE_ID = PiHeaderFieldId.of("ethernet", "ether_type");
    private static final PiHeaderFieldId ETH_DST_ID = PiHeaderFieldId.of("ethernet", "dst_addr");
    private static final PiHeaderFieldId ETH_SRC_ID = PiHeaderFieldId.of("ethernet", "src_addr");
    private static final PiHeaderFieldId IPV4_DST_ID = PiHeaderFieldId.of("ipv4_base", "dst_addr");

    private static final ImmutableBiMap<Integer, PiTableId> TABLE_MAP = ImmutableBiMap.of(
            // If we use the DefaultSingleTable pipeliner, then we need to map only table ID 0,
            // which in this case will be the one used by proxyarp, lldpprovider, etc., i.e. the punt table.
            0, PUNT_TABLE_ID,
            1, L3_FILTER_TBL_ID,
            2, L3_FWD_TBL_ID);

    private ImmutableBiMap<Criterion.Type, PiHeaderFieldId> criterionMap =
            new ImmutableBiMap.Builder<Criterion.Type, PiHeaderFieldId>()
                    .put(Criterion.Type.ETH_DST, ETH_DST_ID)
                    .put(Criterion.Type.ETH_SRC, ETH_SRC_ID)
                    .put(Criterion.Type.ETH_TYPE, ETH_TYPE_ID)
                    .put(Criterion.Type.IPV4_DST, IPV4_DST_ID)
                    .build();

    //FIXME figure out what queque id is, we set as all zeros for now.
    private static final PiActionParam QUEUE_ID_PARAM = new PiActionParam(PiActionParamId.of(QUEUE_ID),
                                                                          ImmutableByteSequence.copyFrom((byte) 0));
    // Only action we need, can be defined statically.
    private static final PiAction SEND_TO_CPU_ACTION = PiAction.builder()
            .withId(PiActionId.of(SEND_TO_CPU))
            .withParameter(QUEUE_ID_PARAM)
            .build();

    @Override
    public PiAction mapTreatment(TrafficTreatment treatment, PiTableId piTableId) throws PiInterpreterException {
        if (piTableId.equals(PUNT_TABLE_ID)) {
            if (treatment.allInstructions().size() != 1) {
                // We understand treatments with only 1 instruction.
                throw new PiPipelineInterpreter.PiInterpreterException("Treatment must have only 1 instruction");
            }

            Instruction instruction = treatment.allInstructions().get(0);

            switch (instruction.type()) {
                case OUTPUT:
                    Instructions.OutputInstruction outInstruction = (Instructions.OutputInstruction) instruction;
                    PortNumber port = outInstruction.port();
                    if (port.equals(CONTROLLER)) {
                        return SEND_TO_CPU_ACTION;
                    } else {
                        throw new PiInterpreterException(format("Egress not supported on %s port", port));
                    }
                default:
                    throw new PiInterpreterException(format("Instruction type '%s' not supported", instruction.type()));
            }
        } else {
            throw new PiInterpreterException(format("Table '%s' not supported", piTableId.name()));
        }
    }

    @Override
    public Optional<PiCounterId> mapTableCounter(PiTableId piTableId) {
        return Optional.empty();
    }

    @Override
    public Collection<PiPacketOperation> mapOutboundPacket(OutboundPacket packet)
            throws PiInterpreterException {

        if (!PACKET_IO_ENABLED) {
            return Collections.emptyList();
        }

        TrafficTreatment treatment = packet.treatment();

        // tor.p4 supports only OUTPUT instructions.
        List<Instructions.OutputInstruction> outInstructions = treatment.allInstructions()
                .stream()
                .filter(i -> i.type().equals(OUTPUT))
                .map(i -> (Instructions.OutputInstruction) i)
                .collect(toList());

        if (treatment.allInstructions().size() != outInstructions.size()) {
            // There are other instructions that are not of type OUTPUT.
            throw new PiInterpreterException("Treatment not supported: " + treatment);
        }

        ImmutableList.Builder<PiPacketOperation> builder = ImmutableList.builder();
        for (Instructions.OutputInstruction outInst : outInstructions) {
            if (outInst.port().isLogical() && !outInst.port().equals(FLOOD)) {
                throw new PiInterpreterException(format("Output on logical port '%s' not supported", outInst.port()));
            } else if (outInst.port().equals(FLOOD)) {
                // Since default.p4 does not support flooding, we create a packet operation for each switch port.
                for (Port port : handler().get(DeviceService.class).getPorts(packet.sendThrough())) {
                    builder.add(createPiPacketOperation(packet.data(), port.number().toLong()));
                }
            } else {
                builder.add(createPiPacketOperation(packet.data(), outInst.port().toLong()));
            }
        }
        return builder.build();
    }

    @Override
    public InboundPacket mapInboundPacket(DeviceId deviceId, PiPacketOperation packetIn)
            throws PiInterpreterException {

        if (!PACKET_IO_ENABLED) {
            return null;
        }

        // FIXME Assuming that the packet is ethernet. is it fine ? tor.p4 can deparse also other packets.
        Ethernet ethPkt = new Ethernet();

        ethPkt.deserialize(packetIn.data().asArray(), 0, packetIn.data().size());

        // Returns the ingress port packet metadata.
        Optional<PiPacketMetadata> packetMetadata = packetIn.metadatas()
                .stream().filter(metadata -> metadata.id().name().equals(INGRESS_PORT))
                .findFirst();

        if (packetMetadata.isPresent()) {
            ImmutableByteSequence portByteSequence = packetMetadata.get().value();
            short s = portByteSequence.asReadOnlyBuffer().getShort();
            ConnectPoint receivedFrom = new ConnectPoint(deviceId, PortNumber.portNumber(s));
            ByteBuffer rawData = ByteBuffer.wrap(packetIn.data().asArray());
            return new DefaultInboundPacket(receivedFrom, ethPkt, rawData);
        } else {
            throw new PiInterpreterException(format(
                    "Missing metadata '%s' in packet-in received from '%s': %s", INGRESS_PORT, deviceId, packetIn));
        }
    }

    private PiPacketOperation createPiPacketOperation(ByteBuffer data, long portNumber) throws PiInterpreterException {
        PiPacketMetadata metadata = createPacketMetadata(portNumber);
        return PiPacketOperation.builder()
                .withType(PACKET_OUT)
                .withData(copyFrom(data))
                .withMetadatas(ImmutableList.of(metadata))
                .build();
    }

    private PiPacketMetadata createPacketMetadata(long portNumber) throws PiInterpreterException {
        try {
            return PiPacketMetadata.builder()
                    .withId(PiPacketMetadataId.of(EGRESS_PORT))
                    .withValue(fit(copyFrom(portNumber), PORT_FIELD_BITWIDTH))
                    .build();
        } catch (ImmutableByteSequence.ByteSequenceTrimException e) {
            throw new PiInterpreterException(format("Port number %d too big, %s", portNumber, e.getMessage()));
        }
    }

    @Override
    public Optional<PiHeaderFieldId> mapCriterionType(Criterion.Type type) {
        return Optional.ofNullable(criterionMap.get(type));
    }

    @Override
    public Optional<Criterion.Type> mapPiHeaderFieldId(PiHeaderFieldId headerFieldId) {
        return Optional.ofNullable(criterionMap.inverse().get(headerFieldId));
    }

    @Override
    public Optional<PiTableId> mapFlowRuleTableId(int flowRuleTableId) {
        return Optional.ofNullable(TABLE_MAP.get(flowRuleTableId));
    }

    @Override
    public Optional<Integer> mapPiTableId(PiTableId piTableId) {
        return Optional.ofNullable(TABLE_MAP.inverse().get(piTableId));
    }
}