/*
 * Copyright 2016-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.tl1.impl;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.util.CharsetUtil;
import org.apache.commons.lang.StringUtils;
import org.onlab.util.Tools;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.DeviceId;
import org.onosproject.tl1.Tl1Command;
import org.onosproject.tl1.Tl1Controller;
import org.onosproject.tl1.Tl1Device;
import org.onosproject.tl1.Tl1Listener;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * Implementation of TL1 controller.
 *
 * Handles the connection and input/output for all registered TL1 devices.
 * Turn on debug logging if you want to see all message I/O.
 *
 * Per device, we track commands using a simple ctag-keyed map. This assumes the client is sending out unique ctag's.
 */
@Component(immediate = true, service = Tl1Controller.class)
public class DefaultTl1Controller implements Tl1Controller {
    private final Logger log = LoggerFactory.getLogger(DefaultTl1Controller.class);

    // TL1 message delimiter (semi colon)
    private static final ByteBuf DELIMITER = Unpooled.copiedBuffer(new char[]{';'}, Charset.defaultCharset());
    private static final String COMPLD = "COMPLD";
    private static final String DENY = "DENY";

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected MastershipService mastershipService;

    private ConcurrentMap<DeviceId, Tl1Device> deviceMap = new ConcurrentHashMap<>();
    // Key: channel, value: map with key ctag, value: future TL1 msg (ctags are assumed unique per device)
    private ConcurrentMap<Channel, ConcurrentMap<Integer, CompletableFuture<String>>> msgMap =
            new ConcurrentHashMap<>();
    private EventLoopGroup workerGroup = new NioEventLoopGroup();
    private Set<Tl1Listener> tl1Listeners = new CopyOnWriteArraySet<>();
    private ExecutorService executor;

    @Activate
    public void activate() {
        executor = Executors.newFixedThreadPool(
                Runtime.getRuntime().availableProcessors(),
                Tools.groupedThreads("onos/tl1controller", "%d", log));
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        executor.shutdown();
        deviceMap.clear();
        msgMap.clear();
        log.info("Stopped");
    }

    @Override
    /**
     * This implementation returns an empty string on failure.
     */
    public CompletableFuture<String> sendMsg(DeviceId deviceId, Tl1Command msg) {
        log.debug("Sending TL1 message to device {}: {}", deviceId, msg);

        Tl1Device device = deviceMap.get(deviceId);
        if (device == null || !device.isConnected() || !mastershipService.isLocalMaster(deviceId)) {
            return CompletableFuture.completedFuture(StringUtils.EMPTY);
        }

        // Create and store completable future, complete it in the channel handler when we receive a response
        CompletableFuture<String> future = new CompletableFuture<>();
        Channel channel = device.channel();
        if (!msgMap.containsKey(channel)) {
            return CompletableFuture.completedFuture(StringUtils.EMPTY);
        }
        msgMap.get(channel).put(msg.ctag(), future);

        // Write message to channel
        channel.writeAndFlush(Unpooled.copiedBuffer(msg.toString(), CharsetUtil.UTF_8));

        return future;
    }

    @Override
    public Optional<Tl1Device> getDevice(DeviceId deviceId) {
        return Optional.ofNullable(deviceMap.get(deviceId));
    }

    @Override
    public boolean addDevice(DeviceId deviceId, Tl1Device device) {
        log.debug("Adding TL1 device {} {}", deviceId);

        // Ignore if device already known
        if (deviceMap.containsKey(deviceId)) {
            log.error("Ignoring duplicate device {}", deviceId);
            return false;
        }

        deviceMap.put(deviceId, device);
        return true;
    }

    @Override
    public void connectDevice(DeviceId deviceId) {
        Tl1Device device = deviceMap.get(deviceId);
        if (device == null || device.isConnected()) {
            return;
        }

        Bootstrap b = new Bootstrap();
        b.group(workerGroup)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(8192, DELIMITER));
                        socketChannel.pipeline().addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
                        // TODO
                        //socketChannel.pipeline().addLast(new Tl1Decoder());
                        socketChannel.pipeline().addLast(new Tl1InboundHandler());
                    }
                })
                .remoteAddress(device.ip().toInetAddress(), device.port())
                .connect()
                .addListener((ChannelFuture channelFuture) -> {
                    if (channelFuture.isSuccess()) {
                        msgMap.put(channelFuture.channel(), new ConcurrentHashMap<>());
                        device.connect(channelFuture.channel());
                        tl1Listeners.forEach(l -> executor.execute(() -> l.deviceConnected(deviceId)));
                    }
                });
    }

    @Override
    public void removeDevice(DeviceId deviceId) {
        disconnectDevice(deviceId);
        deviceMap.remove(deviceId);
    }

    @Override
    public void addListener(Tl1Listener listener) {
        tl1Listeners.add(listener);
    }

    @Override
    public void removeListener(Tl1Listener listener) {
        tl1Listeners.remove(listener);
    }

    @Override
    public void disconnectDevice(DeviceId deviceId) {
        // Ignore if unknown device
        Tl1Device device = deviceMap.get(deviceId);
        if (device == null) {
            return;
        }

        Channel channel = device.channel();
        if (channel != null) {
            channel.close();
            msgMap.remove(channel);
        }

        device.disconnect();
        tl1Listeners.forEach(l -> l.deviceDisconnected(deviceId));
    }

    @Override
    public Set<DeviceId> getDeviceIds() {
        return deviceMap.keySet();
    }

    @Override
    public Collection<Tl1Device> getDevices() {
        return deviceMap.values();
    }

    /**
     * Crude filtering handler that will only complete our stored future upon receiving a TL1 response messages.
     */
    private class Tl1InboundHandler extends SimpleChannelInboundHandler<String> {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
            log.debug("Received TL1 message {}", s);

            // Search for "COMPLD" or "DENY" to identify a TL1 response,
            // then return the remainder of the string.
            String[] words = s.split("\\s");
            for (int i = 0; i < words.length; i++) {
                String w = words[i];
                if (w.startsWith(COMPLD) || w.startsWith(DENY)) {
                    // ctag is just in front of it
                    int ctag = Integer.parseInt(words[i - 1]);
                    // We return everything that follows to the caller (this will lose line breaks and such)
                    String result = Arrays.stream(words).skip(i + 1L).collect(Collectors.joining());
                    // Set future when command is executed, good or bad
                    Map<Integer, CompletableFuture<String>> msg = msgMap.get(ctx.channel());
                    if (msg != null) {
                        CompletableFuture<String> f = msg.remove(ctag);
                        if (f != null) {
                            f.complete(result);
                        }
                    }

                    return;
                }
            }
        }
    }
}
