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

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

        return true;
    }

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