/*
 * 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.onlab.util.SharedExecutors;
import org.onosproject.net.DeviceId;
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.slf4j.Logger;

import java.io.File;
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.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 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;
            }

            //FIXME this hack calls the shell command to set up the ports
            SharedExecutors.getPoolThreadExecutor().submit(() -> runPortCommand(deviceId));

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

        return true;
    }

    // FIXME This is a hack to enable port until we either implement Thrift or gNMI
    private void runPortCommand(DeviceId deviceId) {
        // TODO we should have a more intelligent way of building the command
        final String command;
        if ("device:tofino:11".equals(deviceId.toString())) {
            command = "./pm.py 10.254.1.38 38-port-config.txt";
        } else if ("device:tofino:12".equals(deviceId.toString())) {
            command = "./pm.py 10.254.1.37 37-port-config.txt";
        } else if ("device:tofino:21".equals(deviceId.toString())) {
            command = "./pm.py 10.254.1.40 40-port-config.txt";
        } else if ("device:tofino:22".equals(deviceId.toString())) {
            command = "./pm.py 10.254.1.39 39-port-config.txt";
        } else {
            log.error("Device port config not found: {}", deviceId);
            return;
        }
        try {
            // Give the switch 2 seconds to get settled with the new config
            Thread.sleep(3000);

            String rootDir = System.getenv("ONOS_ROOT");
            if (rootDir == null) {
                log.error("ONOS_ROOT is not set");
                return;
            }
            File workingDirectory = new File(rootDir, "tools/test/tofino-port-auto-setup-tool");
            if (!workingDirectory.isDirectory()) {
                log.error("{} does not exist", workingDirectory);
                return;
            }
            Process process = Runtime.getRuntime().exec(command, null, workingDirectory);
            int exit = process.waitFor();
            if (exit != 0) {
                log.error("port command returned non-zero status {} for device {}", exit, deviceId);
                return;
            }
            log.info("Successfully executed port enable on {}", deviceId);
        } catch (Exception e) {
            log.error("Failed to run port command on {}", deviceId, e);
        }
    }

    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);
    }
}
