/*
 * 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;
    private 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", 100)
            .put("leaf2", 200)
            .build();
    private static final PiTableId TBL_ID_INT_PREP = PiTableId
            .of("int_egress.int_prep");

    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(switchId.get())))
                                                .build())
                                .build())
                .build();

        for (String instMask : ImmutableList.of("0003", "0407")) {
            for (int i = 0; i < 16; i++) {
                PiTableId tableId = PiTableId
                        .of("int_egress.int_metadata_insert.int_inst_" + instMask);
                PiMatchFieldId fmId = PiMatchFieldId
                        .of("hdr.int_header.instruction_mask_" + instMask);
                PiActionId actionId = PiActionId
                        .of("int_egress.int_metadata_insert.int_set_header_" + instMask + "_i" + String.valueOf(i));
                FlowRule intIntrRule = flowRuleBuilder(deviceId, tableId)
                        .withSelector(
                                DefaultTrafficSelector.builder()
                                        .matchPi(
                                                PiCriterion.builder()
                                                        .matchExact(fmId, (byte) i)
                                                        .build())
                                        .build())
                        .withTreatment(
                                DefaultTrafficTreatment.builder()
                                        .piTableAction(PiAction.builder()
                                                               .withId(actionId)
                                                               .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);

        }
    }
}
