/*
 * 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.isis.controller.impl;

import com.fasterxml.jackson.databind.JsonNode;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.AdaptiveReceiveBufferSizePredictor;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onosproject.isis.controller.IsisInterface;
import org.onosproject.isis.controller.IsisNetworkType;
import org.onosproject.isis.controller.IsisProcess;
import org.onosproject.isis.controller.IsisRouterType;
import org.onosproject.isis.controller.topology.IsisAgent;
import org.onosproject.isis.controller.topology.IsisLink;
import org.onosproject.isis.controller.topology.IsisRouter;
import org.onosproject.isis.io.util.IsisConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import static org.onlab.util.Tools.groupedThreads;

/**
 * Representation of an ISIS controller.
 */
public class Controller {
    protected static final int BUFFER_SIZE = 4 * 1024 * 1024;
    private static final Logger log = LoggerFactory.getLogger(Controller.class);
    private static final int RETRY_INTERVAL = 4;
    private final int peerWorkerThreads = 16;
    byte[] configPacket = null;
    private List<IsisProcess> processes = null;
    private IsisChannelHandler isisChannelHandler;
    private NioClientSocketChannelFactory peerExecFactory;
    private ClientBootstrap peerBootstrap = null;
    private TpPort isisPort = TpPort.tpPort(IsisConstants.SPORT);
    private ScheduledExecutorService connectExecutor = null;
    private int connectRetryCounter = 0;
    private int connectRetryTime;
    private ScheduledFuture future = null;
    private IsisAgent agent;

    /**
     * Deactivates ISIS controller.
     */
    public void isisDeactivate() {
        disconnectExecutor();
        processes = null;
        peerExecFactory.shutdown();
    }

    /**
     * Sets ISIS agent.
     *
     * @param agent ISIS agent instance
     */
    public void setAgent(IsisAgent agent) {
        this.agent = agent;
    }


    /**
     * Updates the processes configuration.
     *
     * @param jsonNode json node instance
     */
    public void updateConfig(JsonNode jsonNode) {
        log.debug("Controller::UpdateConfig called");
        configPacket = new byte[IsisConstants.CONFIG_LENGTH];
        byte numberOfInterface = 0; // number of interfaces to configure

        configPacket[0] = (byte) 0xFF; // its a conf packet - identifier
        List<IsisProcess> isisProcesses = getConfig(jsonNode);
        for (IsisProcess isisProcess : isisProcesses) {
            log.debug("IsisProcessDetails : " + isisProcess);
            for (IsisInterface isisInterface : isisProcess.isisInterfaceList()) {
                DefaultIsisInterface isisInterfaceImpl = (DefaultIsisInterface) isisInterface;
                log.debug("IsisInterfaceDetails : " + isisInterface);
                numberOfInterface++;
                configPacket[2 * numberOfInterface] = (byte) isisInterfaceImpl.interfaceIndex();
                if (isisInterface.networkType() == IsisNetworkType.BROADCAST &&
                        isisInterfaceImpl.reservedPacketCircuitType() == IsisRouterType.L1.value()) {
                    configPacket[(2 * numberOfInterface) + 1] = (byte) 0;
                } else if (isisInterface.networkType() == IsisNetworkType.BROADCAST &&
                        isisInterfaceImpl.reservedPacketCircuitType() == IsisRouterType.L2.value()) {
                    configPacket[(2 * numberOfInterface) + 1] = (byte) 1;
                } else if (isisInterface.networkType() == IsisNetworkType.P2P) {
                    configPacket[(2 * numberOfInterface) + 1] = (byte) 2;
                } else if (isisInterface.networkType() == IsisNetworkType.BROADCAST &&
                        isisInterfaceImpl.reservedPacketCircuitType() == IsisRouterType.L1L2.value()) {
                    configPacket[(2 * numberOfInterface) + 1] = (byte) 3;
                }
            }
        }
        configPacket[1] = numberOfInterface;
        //First time configuration
        if (processes == null) {
            if (!isisProcesses.isEmpty()) {
                processes = isisProcesses;
                connectPeer();
            }
        } else {
            isisChannelHandler.updateInterfaceMap(isisProcesses);
            //Send the config packet
            isisChannelHandler.sentConfigPacket(configPacket);
        }
    }

    /**
     * Initializes the netty client channel connection.
     */
    private void initConnection() {
        if (peerBootstrap != null) {
            return;
        }
        peerBootstrap = createPeerBootStrap();

        peerBootstrap.setOption("reuseAddress", true);
        peerBootstrap.setOption("tcpNoDelay", true);
        peerBootstrap.setOption("keepAlive", true);
        peerBootstrap.setOption("receiveBufferSize", Controller.BUFFER_SIZE);
        peerBootstrap.setOption("receiveBufferSizePredictorFactory",
                new FixedReceiveBufferSizePredictorFactory(
                        Controller.BUFFER_SIZE));
        peerBootstrap.setOption("receiveBufferSizePredictor",
                new AdaptiveReceiveBufferSizePredictor(64, 1024, 65536));
        peerBootstrap.setOption("child.keepAlive", true);
        peerBootstrap.setOption("child.tcpNoDelay", true);
        peerBootstrap.setOption("child.sendBufferSize", Controller.BUFFER_SIZE);
        peerBootstrap.setOption("child.receiveBufferSize", Controller.BUFFER_SIZE);
        peerBootstrap.setOption("child.receiveBufferSizePredictorFactory",
                new FixedReceiveBufferSizePredictorFactory(
                        Controller.BUFFER_SIZE));
        peerBootstrap.setOption("child.reuseAddress", true);

        isisChannelHandler = new IsisChannelHandler(this, processes);
        ChannelPipelineFactory pfact = new IsisPipelineFactory(isisChannelHandler);
        peerBootstrap.setPipelineFactory(pfact);
    }

    /**
     * Creates peer boot strap.
     *
     * @return client bootstrap instance
     */
    private ClientBootstrap createPeerBootStrap() {

        if (peerWorkerThreads == 0) {
            peerExecFactory = new NioClientSocketChannelFactory(
                    Executors.newCachedThreadPool(groupedThreads("onos/isis", "boss-%d")),
                    Executors.newCachedThreadPool(groupedThreads("onos/isis", "worker-%d")));
            return new ClientBootstrap(peerExecFactory);
        } else {
            peerExecFactory = new NioClientSocketChannelFactory(
                    Executors.newCachedThreadPool(groupedThreads("onos/isis", "boss-%d")),
                    Executors.newCachedThreadPool(groupedThreads("onos/isis", "worker-%d")),
                    peerWorkerThreads);
            return new ClientBootstrap(peerExecFactory);
        }
    }

    /**
     * Gets all configured processes.
     *
     * @return all configured processes
     */
    public List<IsisProcess> getAllConfiguredProcesses() {
        return processes;
    }

    /**
     * Gets the list of processes configured.
     *
     * @param json posted json
     * @return list of processes configured
     */
    private List<IsisProcess> getConfig(JsonNode json) {
        List<IsisProcess> isisProcessesList = new ArrayList<>();
        JsonNode jsonNodes = json;
        if (jsonNodes == null) {
            return isisProcessesList;
        }
        jsonNodes.forEach(jsonNode -> {
            List<IsisInterface> interfaceList = new ArrayList<>();
            for (JsonNode jsonNode1 : jsonNode.path(IsisConstants.INTERFACE)) {
                IsisInterface isisInterface = new DefaultIsisInterface();
                String index = jsonNode1.path(IsisConstants.INTERFACEINDEX).asText();
                if (isPrimitive(index)) {
                    int input = Integer.parseInt(index);
                    if (input < 1 || input > 255) {
                        log.debug("Wrong interface index: {}", index);
                        continue;
                    }
                    isisInterface.setInterfaceIndex(Integer.parseInt(index));
                } else {
                    log.debug("Wrong interface index {}", index);
                    continue;
                }
                Ip4Address ipAddress = getInterfaceIp(isisInterface.interfaceIndex());
                if (ipAddress != null && !ipAddress.equals(IsisConstants.DEFAULTIP)) {
                    isisInterface.setInterfaceIpAddress(ipAddress);
                } else {
                    log.debug("Wrong interface index {}. No matching interface in system.", index);
                    continue;
                }
                MacAddress macAddress = getInterfaceMac(isisInterface.interfaceIndex());
                if (macAddress != null) {
                    isisInterface.setInterfaceMacAddress(macAddress);
                } else {
                    log.debug("Wrong interface index {}. No matching interface in system.", index);
                    continue;
                }
                String mask = getInterfaceMask(isisInterface.interfaceIndex());
                if (mask != null) {
                    try {
                        isisInterface.setNetworkMask(InetAddress.getByName(mask).getAddress());
                    } catch (UnknownHostException e) {
                        log.debug("Wrong interface index {}. Error while getting network mask.", index);
                    }
                } else {
                    log.debug("Wrong interface index {}. Error while getting network mask.", index);
                    continue;
                }
                isisInterface.setIntermediateSystemName(jsonNode1
                        .path(IsisConstants.INTERMEDIATESYSTEMNAME)
                        .asText());
                String systemId = jsonNode1.path(IsisConstants.SYSTEMID).asText();
                if (isValidSystemId(systemId)) {
                    isisInterface.setSystemId(systemId);
                } else {
                    log.debug("Wrong systemId: {} for interface index {}.", systemId, index);
                    continue;
                }
                String circuitType = jsonNode1.path(IsisConstants.RESERVEDPACKETCIRCUITTYPE).asText();
                if (isPrimitive(circuitType)) {
                    int input = Integer.parseInt(circuitType);
                    if (input < 1 || input > 3) {
                        log.debug("Wrong ReservedPacketCircuitType: {} for interface index {}.", circuitType, index);
                        continue;
                    }
                    isisInterface.setReservedPacketCircuitType(input);
                } else {
                    log.debug("Wrong ReservedPacketCircuitType: {} for interface index {}.", circuitType, index);
                    continue;
                }
                String networkType = jsonNode1.path(IsisConstants.NETWORKTYPE).asText();
                if (isPrimitive(networkType)) {
                    int input = Integer.parseInt(networkType);
                    if (input < 1 || input > 2) {
                        log.debug("Wrong networkType: {} for interface index {}.", networkType, index);
                        continue;
                    }
                    isisInterface.setNetworkType(IsisNetworkType.get(input));
                } else {
                    log.debug("Wrong networkType: {} for interface index {}.", networkType, index);
                    continue;
                }
                String areaAddress = jsonNode1.path(IsisConstants.AREAADDRESS).asText();
                if (isPrimitive(areaAddress)) {
                    if (areaAddress.length() > 7) {
                        log.debug("Wrong areaAddress: {} for interface index {}.", areaAddress, index);
                        continue;
                    }
                    isisInterface.setAreaAddress(areaAddress);
                } else {
                    log.debug("Wrong areaAddress: {} for interface index {}.", areaAddress, index);
                    continue;
                }
                String circuitId = jsonNode1.path(IsisConstants.CIRCUITID).asText();
                if (isPrimitive(circuitId)) {
                    int input = Integer.parseInt(circuitId);
                    if (input < 1) {
                        log.debug("Wrong circuitId: {} for interface index {}.", circuitId, index);
                        continue;
                    }
                    isisInterface.setCircuitId(circuitId);
                } else {
                    log.debug("Wrong circuitId: {} for interface index {}.", circuitId, index);
                    continue;
                }
                String holdingTime = jsonNode1.path(IsisConstants.HOLDINGTIME).asText();
                if (isPrimitive(holdingTime)) {
                    int input = Integer.parseInt(holdingTime);
                    if (input < 1 || input > 255) {
                        log.debug("Wrong holdingTime: {} for interface index {}.", holdingTime, index);
                        continue;
                    }
                    isisInterface.setHoldingTime(input);
                } else {
                    log.debug("Wrong holdingTime: {} for interface index {}.", holdingTime, index);
                    continue;
                }
                String helloInterval = jsonNode1.path(IsisConstants.HELLOINTERVAL).asText();
                if (isPrimitive(helloInterval)) {
                    int interval = Integer.parseInt(helloInterval);
                    if (interval > 0 && interval <= 255) {
                        isisInterface.setHelloInterval(interval);
                    } else {
                        log.debug("Wrong hello interval: {} for interface index {}.", helloInterval, index);
                        continue;
                    }
                } else {
                    log.debug("Wrong hello interval: {} for interface index {}.", helloInterval, index);
                    continue;
                }
                interfaceList.add(isisInterface);
            }
            if (!interfaceList.isEmpty()) {
                IsisProcess process = new DefaultIsisProcess();
                process.setProcessId(jsonNode.path(IsisConstants.PROCESSESID).asText());
                process.setIsisInterfaceList(interfaceList);
                isisProcessesList.add(process);
            }
        });

        return isisProcessesList;
    }

    /**
     * Returns interface MAC by index.
     *
     * @param interfaceIndex interface index
     * @return interface IP by index
     */
    private MacAddress getInterfaceMac(int interfaceIndex) {
        MacAddress macAddress = null;
        try {
            NetworkInterface networkInterface = NetworkInterface.getByIndex(interfaceIndex);
            macAddress = MacAddress.valueOf(networkInterface.getHardwareAddress());
        } catch (Exception e) {
            log.debug("Error while getting Interface IP by index");
            return macAddress;
        }

        return macAddress;
    }

    /**
     * Returns interface IP by index.
     *
     * @param interfaceIndex interface index
     * @return interface IP by index
     */
    private Ip4Address getInterfaceIp(int interfaceIndex) {
        Ip4Address ipAddress = null;
        try {
            NetworkInterface networkInterface = NetworkInterface.getByIndex(interfaceIndex);
            Enumeration ipAddresses = networkInterface.getInetAddresses();
            while (ipAddresses.hasMoreElements()) {
                InetAddress address = (InetAddress) ipAddresses.nextElement();
                if (!address.isLinkLocalAddress()) {
                    ipAddress = Ip4Address.valueOf(address.getAddress());
                    break;
                }
            }
        } catch (Exception e) {
            log.debug("Error while getting Interface IP by index");
            return IsisConstants.DEFAULTIP;
        }
        return ipAddress;
    }

    /**
     * Returns interface MAC by index.
     *
     * @param interfaceIndex interface index
     * @return interface IP by index
     */
    private String getInterfaceMask(int interfaceIndex) {
        String subnetMask = null;
        try {
            Ip4Address ipAddress = getInterfaceIp(interfaceIndex);
            NetworkInterface networkInterface = NetworkInterface.getByInetAddress(
                    InetAddress.getByName(ipAddress.toString()));
            Enumeration ipAddresses = networkInterface.getInetAddresses();
            int index = 0;
            while (ipAddresses.hasMoreElements()) {
                InetAddress address = (InetAddress) ipAddresses.nextElement();
                if (!address.isLinkLocalAddress()) {
                    break;
                }
                index++;
            }
            int prfLen = networkInterface.getInterfaceAddresses().get(index).getNetworkPrefixLength();
            int shft = 0xffffffff << (32 - prfLen);
            int oct1 = ((byte) ((shft & 0xff000000) >> 24)) & 0xff;
            int oct2 = ((byte) ((shft & 0x00ff0000) >> 16)) & 0xff;
            int oct3 = ((byte) ((shft & 0x0000ff00) >> 8)) & 0xff;
            int oct4 = ((byte) (shft & 0x000000ff)) & 0xff;
            subnetMask = oct1 + "." + oct2 + "." + oct3 + "." + oct4;
        } catch (Exception e) {
            log.debug("Error while getting Interface network mask by index");
            return subnetMask;
        }
        return subnetMask;
    }

    /**
     * Checks if primitive or not.
     *
     * @param value input value
     * @return true if number else false
     */
    private boolean isPrimitive(String value) {
        boolean status = true;
        value = value.trim();
        if (value.length() < 1) {
            return false;
        }
        for (int i = 0; i < value.length(); i++) {
            char c = value.charAt(i);
            if (!Character.isDigit(c)) {
                status = false;
                break;
            }
        }

        return status;
    }

    /**
     * Checks if system id is valid or not.
     *
     * @param value input value
     * @return true if valid else false
     */
    private boolean isValidSystemId(String value) {
        value = value.trim();
        boolean status = true;
        if (value.length() != 14) {
            return false;
        }
        for (int i = 0; i < value.length(); i++) {
            char c = value.charAt(i);
            if (!Character.isDigit(c)) {
                if (!((i == 4 || i == 9) && c == '.')) {
                    status = false;
                    break;
                }
            }
        }

        return status;
    }

    /**
     * Disconnects the executor.
     */
    public void disconnectExecutor() {
        if (connectExecutor != null) {
            future.cancel(true);
            connectExecutor.shutdownNow();
            connectExecutor = null;
        }
    }

    /**
     * Connects to peer.
     */
    public void connectPeer() {
        scheduleConnectionRetry(this.connectRetryTime);
    }

    /**
     * Retry connection with exponential back-off mechanism.
     *
     * @param retryDelay retry delay
     */
    private void scheduleConnectionRetry(long retryDelay) {
        if (connectExecutor == null) {
            connectExecutor = Executors.newSingleThreadScheduledExecutor();
        }
        future = connectExecutor.schedule(new ConnectionRetry(), retryDelay, TimeUnit.MINUTES);
    }

    /**
     * Adds device details.
     *
     * @param isisRouter ISIS router instance
     */
    public void addDeviceDetails(IsisRouter isisRouter) {
        agent.addConnectedRouter(isisRouter);
    }

    /**
     * Removes device details.
     *
     * @param isisRouter Isis router instance
     */
    public void removeDeviceDetails(IsisRouter isisRouter) {
        agent.removeConnectedRouter(isisRouter);
    }

    /**
     * Adds link details.
     *
     * @param isisLink ISIS link instance
     */
    public void addLinkDetails(IsisLink isisLink) {
        agent.addLink(isisLink);
    }

    /**
     * Removes link details.
     *
     * @param isisLink ISIS link instance
     */
    public void removeLinkDetails(IsisLink isisLink) {
        agent.deleteLink(isisLink);
    }

    /**
     * Returns the isisAgent instance.
     *
     * @return agent
     */
    public IsisAgent agent() {
        return this.agent;
    }

    /**
     * Implements ISIS connection and manages connection to peer with back-off mechanism in case of failure.
     */
    class ConnectionRetry implements Runnable {
        @Override
        public void run() {
            log.debug("Connect to peer {}", IsisConstants.SHOST);
            initConnection();
            isisChannelHandler.sentConfigPacket(configPacket);
            InetSocketAddress connectToSocket = new InetSocketAddress(IsisConstants.SHOST, isisPort.toInt());
            try {
                peerBootstrap.connect(connectToSocket).addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (!future.isSuccess()) {
                            connectRetryCounter++;
                            log.error("Connection failed, ConnectRetryCounter {} remote host {}", connectRetryCounter,
                                    IsisConstants.SHOST);
                            /*
                             * Reconnect to peer on failure is exponential till 4 mins, later on retry after every 4
                             * mins.
                             */
                            if (connectRetryTime < RETRY_INTERVAL) {
                                connectRetryTime = (connectRetryTime != 0) ? connectRetryTime * 2 : 1;
                            }
                            scheduleConnectionRetry(connectRetryTime);
                        } else {
                            //Send the config packet
                            isisChannelHandler.sentConfigPacket(configPacket);
                            connectRetryCounter++;
                            log.info("Connected to remote host {}, Connect Counter {}", IsisConstants.SHOST,
                                    connectRetryCounter);
                            disconnectExecutor();

                            return;
                        }
                    }
                });
            } catch (Exception e) {
                log.info("Connect peer exception : " + e.toString());
                disconnectExecutor();
            }
        }
    }
}