/*
 * Copyright 2018-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.intdemo;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang.ArrayUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ip4Address;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.criteria.PiCriterion;
import org.onosproject.net.pi.model.PiActionId;
import org.onosproject.net.pi.model.PiActionParamId;
import org.onosproject.net.pi.model.PiMatchFieldId;
import org.onosproject.net.pi.model.PiPipeconfId;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.net.pi.service.PiPipeconfService;
import org.slf4j.Logger;

import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;

import static org.onlab.util.ImmutableByteSequence.copyFrom;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Implementation of an upgradable fabric app for the Basic pipeconf (basic.p4)
 * with ECMP support.
 */
@Component(immediate = true)
public class IntDemoApp {

    private static final int DEFAULT_TEID = 0;
    protected final Logger log = getLogger(getClass());

    private static final String SPGW_INT_PIPECONF_KEYWORD = "spgw-int";
    private static final String SPGW_DEVICE_KEYWORD = "leaf2";
    private static final Ip4Address S1U_SGW_ADDR = Ip4Address.valueOf("140.0.0.2");

    private static final Collection<String> UE_ADDRS = ImmutableList.of(
            "160.0.2.1", "160.0.2.2", "160.0.2.3", "160.0.2.4", "160.0.2.5");

    private static final Map<String, Integer> SWITCH_ID_MAP = new ImmutableMap.Builder<String, Integer>()
            .put("leaf1", 0)
            .put("leaf2", 1)
            .build();

    private static final PiTableId TBL_ID_INT_INST = PiTableId
            .of("int_egress.int_metadata_insert.int_inst_0003");
    private static final PiTableId TBL_ID_INT_PREP = PiTableId
            .of("int_egress.int_prep");

    private static final PiMatchFieldId FM_ID_INST_MASK = PiMatchFieldId
            .of("hdr.int_header.instruction_mask_0003");

    private static final PiActionId ACT_ID_INST_ALL = PiActionId
            .of("int_egress.int_metadata_insert.int_set_header_0003_i15");
    private static final PiActionId ACT_ID_INT_TRANSIT = PiActionId
            .of("int_egress.int_transit");

    private static final PiActionParamId ACTP_ID_SWITCH_ID = PiActionParamId
            .of("switch_id");

    private static final PiTableId TBL_ID_UE_FILTER = PiTableId
            .of("spgw_ingress.ue_filter_table");
    private static final PiTableId TBL_ID_DL_SESS_LOOKUP = PiTableId
            .of("spgw_ingress.dl_sess_lookup");
    private static final PiMatchFieldId MF_ID_IPV4_DST = PiMatchFieldId
            .of("ipv4.dst_addr");
    private static final PiActionId ACT_ID_SET_DL_SESS_INFO = PiActionId
            .of("spgw_ingress.set_dl_sess_info");
    private static final PiActionParamId PARAM_S1U_ENB_ADDR = PiActionParamId
            .of("s1u_enb_addr");
    private static final PiActionParamId PARAM_ID_S1U_SGW_ADDR = PiActionParamId
            .of("s1u_sgw_addr");
    private static final PiAction NO_ACTION = PiAction.builder()
            .withId(PiActionId.of("NoAction"))
            .build();
    private static final PiActionParamId ACTP_TEID = PiActionParamId
            .of("teid");

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    private DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    private FlowRuleService flowRuleService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    private CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    private PiPipeconfService piPipeconfService;

    private final DeviceListener deviceListener = new InternalDeviceListener();

    private ApplicationId appId;

    @Activate
    public void activate() {
        log.info("Starting...");
        appId = coreService.registerApplication("org.onosproject.int-demo");
        deviceService.getDevices().forEach(d -> checkDevice(d.id()));
        deviceService.addListener(deviceListener);
        log.info("STARTED", appId.id());
    }

    @Deactivate
    public void deactivate() {
        log.info("Stopping...");
        deviceService.removeListener(deviceListener);
        flowRuleService.removeFlowRulesById(appId);
        log.info("STOPPED");
    }

    private void confIntSwitch(DeviceId deviceId) {
        Optional<Integer> switchId = SWITCH_ID_MAP.keySet().stream()
                .filter(k -> deviceId.toString().contains(k))
                .findFirst()
                .map(SWITCH_ID_MAP::get);

        if (!switchId.isPresent()) {
            log.error("Unknown INT switch ID for device {}", deviceId);
            return;
        }

        log.info("Configuring device {} for INT transit capability: switchId={}...", deviceId, switchId.get());

        FlowRule intPrepRule = flowRuleBuilder(deviceId, TBL_ID_INT_PREP)
                .withSelector(DefaultTrafficSelector.emptySelector())
                .withTreatment(
                        DefaultTrafficTreatment.builder()
                                .piTableAction(
                                        PiAction.builder()
                                                .withId(ACT_ID_INT_TRANSIT)
                                                .withParameter(new PiActionParam(
                                                        ACTP_ID_SWITCH_ID, copyFrom(0)))
                                                .build())
                                .build())
                .build();

        FlowRule intIntrRule = flowRuleBuilder(deviceId, TBL_ID_INT_INST)
                .withSelector(
                        DefaultTrafficSelector.builder()
                                .matchPi(
                                        PiCriterion.builder()
                                                .matchExact(FM_ID_INST_MASK, (byte) 0x0F)
                                                .build())
                                .build())
                .withTreatment(
                        DefaultTrafficTreatment.builder()
                                .piTableAction(PiAction.builder()
                                                       .withId(ACT_ID_INST_ALL)
                                                       .build())
                                .build())
                .build();

        flowRuleService.applyFlowRules(intPrepRule, intIntrRule);
    }

    private void confSpgw(DeviceId deviceId) {
        log.info("Configuring device {} for SPGW downlink processing...", deviceId);
        UE_ADDRS.stream()
                .map(Ip4Address::valueOf)
                .forEach(ueAddr -> {
                    flowRuleService.applyFlowRules(ueFilterRule(deviceId, ueAddr));
                    flowRuleService.applyFlowRules(
                            dlSessLookupRule(deviceId, ueAddr, DEFAULT_TEID, ueAddr, S1U_SGW_ADDR)
                    );
                });
    }

    private FlowRule ueFilterRule(DeviceId deviceId, Ip4Address ueAddr) {
        final PiCriterion piCriterion = PiCriterion.builder()
                .matchLpm(MF_ID_IPV4_DST, ueAddr.toOctets(), 32)
                .build();

        return flowRuleBuilder(deviceId, TBL_ID_UE_FILTER)
                .withSelector(DefaultTrafficSelector.builder()
                                      .matchPi(piCriterion)
                                      .build())
                .withTreatment(DefaultTrafficTreatment.builder()
                                       .piTableAction(NO_ACTION)
                                       .build())
                .build();
    }

    private FlowRule dlSessLookupRule(DeviceId deviceId, Ip4Address ueAddr, long teid,
                                      Ip4Address enbAddr, Ip4Address s1uAddr) {

        // FIXME: the long teid is obtained from the wrong byte order
        ImmutableByteSequence teidBs = copyFrom(teid);
        byte[] byteArray = teidBs.asArray();
        ArrayUtils.reverse(byteArray);
        byte[] trimmedArray = Arrays.copyOfRange(byteArray, 0, 4);
        ImmutableByteSequence revTeidBs = copyFrom(trimmedArray);

        // Add rule to
        final PiAction action = PiAction.builder()
                .withId(ACT_ID_SET_DL_SESS_INFO)
                .withParameter(new PiActionParam(ACTP_TEID, revTeidBs))
                .withParameter(new PiActionParam(PARAM_S1U_ENB_ADDR,
                                                 copyFrom(enbAddr.toOctets())))
                .withParameter(new PiActionParam(PARAM_ID_S1U_SGW_ADDR,
                                                 copyFrom(s1uAddr.toOctets())))
                .build();

        final PiCriterion piCriterion = PiCriterion.builder()
                .matchExact(MF_ID_IPV4_DST, ueAddr.toOctets())
                .build();

        return flowRuleBuilder(deviceId, TBL_ID_DL_SESS_LOOKUP)
                .withSelector(DefaultTrafficSelector.builder()
                                      .matchPi(piCriterion)
                                      .build())
                .withTreatment(DefaultTrafficTreatment.builder()
                                       .piTableAction(action)
                                       .build())
                .build();
    }

    /**
     * Returns a new, pre-configured flow rule builder.
     *
     * @param did     a device id
     * @param tableId a table id
     * @return a new flow rule builder
     */
    private FlowRule.Builder flowRuleBuilder(DeviceId did, PiTableId tableId) {
        return DefaultFlowRule.builder()
                .forDevice(did)
                .forTable(tableId)
                .fromApp(appId)
                .withPriority(0)
                .makePermanent();
    }

    private void checkDevice(DeviceId deviceId) {
        // If device has pipeconf spgw-int
        Optional<PiPipeconfId> pipeconf = piPipeconfService.ofDevice(deviceId);

        if (!pipeconf.isPresent() || !pipeconf.get().id().contains(SPGW_INT_PIPECONF_KEYWORD)) {
            log.info("Device {} has no pipeconf associated or pipeconf is not SPGW/INT-capable, ignoring", deviceId);
            return;
        }

        confIntSwitch(deviceId);

        if (deviceId.toString().contains(SPGW_DEVICE_KEYWORD)) {
            confSpgw(deviceId);
        }
    }

    private class InternalDeviceListener implements DeviceListener {

        @Override
        public void event(DeviceEvent event) {
            if (event.type() != DeviceEvent.Type.DEVICE_ADDED) {
                return;
            }
            DeviceId deviceId = event.subject().id();
            checkDevice(deviceId);

        }
    }
}
