/*
 * 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.drivers.barefoot;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.commons.io.IOUtils;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TMultiplexedProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.onlab.util.SharedExecutors;
import org.onosproject.drivers.barefoot.pal.pal;
import org.onosproject.drivers.barefoot.pal.pal_autoneg_policy_t;
import org.onosproject.drivers.barefoot.pal.pal_fec_type_t;
import org.onosproject.drivers.barefoot.pal.pal_port_speed_t;
import org.onosproject.incubator.net.config.basics.PortDescriptionsConfig;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.model.PiPipeconf.ExtensionType;
import org.onosproject.net.pi.model.PiPipelineProgrammable;
import org.onosproject.p4runtime.api.P4RuntimeClient;
import org.onosproject.p4runtime.api.P4RuntimeController;
import org.onosproject.provider.general.device.api.GeneralProviderDeviceConfig;
import org.slf4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Implementation of the PiPipelineProgrammable for BMv2.
 */
public class TofinoPipelineProgrammable extends AbstractHandlerBehaviour implements PiPipelineProgrammable {

    // FIXME: default pipeconf should depend on the system. Maybe pass it via netcfg?
    private static final PiPipeconf DEFAULT_PIPECONF = TofinoDefaultPipeconfFactory.getMavericks();
    private static final String P4RUNTIME = "p4runtime";
    private static final String PROTOCOL_KEY_IP = "ip";
    private static final String DEVICE_ID = "deviceId";
    private static final int PAL_MGMT_PORT = 9090;
    private static final String PAL_THRIFT_SERVICE = "pal";

    private final Logger log = getLogger(getClass());

    @Override
    public CompletableFuture<Boolean> deployPipeconf(PiPipeconf pipeconf) {

        CompletableFuture<Boolean> result = new CompletableFuture<>();

        SharedExecutors.getPoolThreadExecutor().submit(() -> result.complete(doDeployConfig(pipeconf)));

        return result;
    }

    private boolean doDeployConfig(PiPipeconf pipeconf) {

        P4RuntimeController controller = handler().get(P4RuntimeController.class);

        DeviceId deviceId = handler().data().deviceId();

        if (!controller.hasClient(deviceId)) {
            log.warn("Unable to find client for {}, aborting pipeconf deploy", deviceId);
            return false;
        }

        P4RuntimeClient client = controller.getClient(deviceId);

        //creating the ByteBuffer with all the needed elements to set the pipeline on the device
        ByteBuffer pipelineBuffer = createPipelineBuffer(pipeconf,
                ImmutableList.of(ExtensionType.TOFINO_BIN, ExtensionType.TOFINO_CONTEXT_JSON));

        try {
            if (!client.setPipelineConfig(pipeconf, pipelineBuffer).get()) {
                log.warn("Unable to deploy pipeconf {} to {}", pipeconf.id(), deviceId);
                return false;
            }

            // It would be more logical to have this performed at device handshake, but P4runtime would reject any
            // command if a P4info has not been set first.
            if (!client.initStreamChannel().get()) {
                log.warn("Unable to init stream channel to {}.", deviceId);
                return false;
            }

            SharedExecutors.getPoolThreadExecutor().submit(() -> setupPorts(deviceId));

        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }

        return true;
    }

    // FIXME Currently use thrift, may use gNMI to manage it in the future.
    private void setupPorts(DeviceId deviceId) {
        NetworkConfigService netcfgService = handler().get(NetworkConfigService.class);
        GeneralProviderDeviceConfig providerConfig =
                netcfgService.getConfig(deviceId, GeneralProviderDeviceConfig.class);
        PortDescriptionsConfig portConfig =
                netcfgService.getConfig(deviceId, PortDescriptionsConfig.class);

        Map<String, String> values =
                providerConfig.protocolsInfo().get(P4RUNTIME).configValues();
        String ip = values.get(PROTOCOL_KEY_IP);
        byte tofinoDeviceId = Byte.parseByte(values.get(DEVICE_ID));

        List<PortDescription> ports = portConfig.portDescriptions();
        ports.forEach(port -> {
            pal_port_speed_t speed = getPortSpeed(port.portSpeed());
            addAndEnablePort(ip, tofinoDeviceId, (int) port.portNumber().toLong(), speed);
        });
    }

    private pal_port_speed_t getPortSpeed(long speed) {
        // Mbps -> BF_SPEED (1G~100G)
        speed = speed / 1000;

        if (speed >= 100) {
            return pal_port_speed_t.BF_SPEED_100G;
        }
        if (speed >= 50) {
            return pal_port_speed_t.BF_SPEED_50G;
        }
        if (speed >= 40) {
            return pal_port_speed_t.BF_SPEED_40G;
        }
        if (speed >= 25) {
            return pal_port_speed_t.BF_SPEED_25G;
        }
        if (speed >= 10) {
            return pal_port_speed_t.BF_SPEED_10G;
        }

        return pal_port_speed_t.BF_SPEED_1G;
    }

    private void addAndEnablePort(String ip, byte deviceId, int dp, pal_port_speed_t speed) {
        TTransport transport = null;
        try {
            transport = new TSocket(ip, PAL_MGMT_PORT);
            transport.open();
            TProtocol protocol = new TBinaryProtocol(transport);
            TMultiplexedProtocol mProtocol = new TMultiplexedProtocol(protocol,
                                                                      PAL_THRIFT_SERVICE);
            pal.Client client = new pal.Client(mProtocol);

            client.pal_port_add(deviceId, dp, speed, pal_fec_type_t.BF_FEC_TYP_NONE);
            client.pal_port_an_set(deviceId, dp, pal_autoneg_policy_t.BF_AN_FORCE_DISABLE);
            client.pal_port_enable(deviceId, dp);
            transport.close();
        } catch (TException x) {
            log.error("Error adding port {} to device {} ({})", dp, deviceId, ip, x);
        } finally {
            if (transport != null) {
                transport.close();
            }
        }
    }

    private ByteBuffer createPipelineBuffer(PiPipeconf pipeconf, List<ExtensionType> targetConfigExtTypes) {
        if (targetConfigExtTypes == null || targetConfigExtTypes.isEmpty() || isNullOrEmpty(pipeconf.id().toString())) {

            log.warn("Not enough information to deploy the Pipeconf {} on the switch {}, {}", pipeconf.id(),
                    targetConfigExtTypes);
        } else {
            List<ByteBuffer> buffers = Lists.newLinkedList();
            //Name of the pipeconf.
            //Appears to be an arbitrary name and unrelated to p4 program
            String name = pipeconf.id().toString();
            buffers.add(ByteBuffer.allocate(4 + name.length())
                                           .order(ByteOrder.LITTLE_ENDIAN)
                                           .putInt(name.length())
                                           .put(name.getBytes(StandardCharsets.UTF_8)));

            // Build buffers for all the extensions needed to deploy the pipeconf to Tofino
            targetConfigExtTypes.forEach(targetConfigExtType -> {
                if (!pipeconf.extension(targetConfigExtType).isPresent()) {
                    // FIXME this will break the expected data format; the resulting buffer will be invalid.
                    // FIXME Consider a stronger response here, like an exception.
                    log.warn("Missing extension {} in pipeconf {}", targetConfigExtType, pipeconf.id());
                }
                InputStream targetConfig = pipeconf.extension(targetConfigExtType).get();
                try {
                    log.info("Setting extension {} in pipeconf {}", targetConfigExtType, pipeconf.id());
                    byte[] bin = IOUtils.toByteArray(targetConfig);
                    //length and byte of every extension
                    buffers.add(ByteBuffer.allocate(4 + bin.length)
                                          .order(ByteOrder.LITTLE_ENDIAN)
                                          .putInt(bin.length)
                                          .put(bin));
                } catch (IOException ex) {
                    // FIXME this will break the expected data format; the resulting buffer will be invalid.
                    // FIXME Consider a stronger response here, like an exception.
                    log.warn("Unable to load target-specific config for {}", ex.getMessage());
                }
            });

            // Merge the buffers
            int len = buffers.stream().mapToInt(Buffer::limit).sum();
            ByteBuffer deviceData = ByteBuffer.allocate(len);
            for (ByteBuffer b : buffers) {
                deviceData.put((ByteBuffer) b.flip());
            }
            deviceData.flip(); // prepare for reading
            return deviceData.asReadOnlyBuffer();
        }
        return null;
    }

    @Override
    public Optional<PiPipeconf> getDefaultPipeconf() {
        return Optional.of(DEFAULT_PIPECONF);
    }
}
