/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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 org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
import org.jboss.netty.handler.timeout.ReadTimeoutException;
import org.onlab.packet.Ip4Address;
import org.onosproject.isis.controller.IsisInterface;
import org.onosproject.isis.controller.IsisLsdb;
import org.onosproject.isis.controller.IsisMessage;
import org.onosproject.isis.controller.IsisProcess;
import org.onosproject.isis.controller.impl.lsdb.DefaultIsisLsdb;
import org.onosproject.isis.exceptions.IsisParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;

/**
 * Channel handler deals with the ISIS channel connection.
 * Also it dispatches messages to the appropriate handlers for processing.
 */
public class IsisChannelHandler extends IdleStateAwareChannelHandler {

    private static final Logger log = LoggerFactory.getLogger(IsisChannelHandler.class);
    private static Map<Integer, Object> isisDb = null;
    private Channel channel = null;
    private Controller controller;
    private List<IsisProcess> processes = null;
    private List<ScheduledExecutorService> executorList = new ArrayList<>();
    private byte[] configPacket = null;
    private Map<Integer, IsisInterface> isisInterfaceMap = new ConcurrentHashMap<>();
    private IsisLsdb isisLsdb = new DefaultIsisLsdb();
    private List<Ip4Address> interfaceIps = new ArrayList<>();

    /**
     * Creates an instance of ISIS channel handler.
     *
     * @param controller controller instance
     * @param processes  list of configured processes
     */
    public IsisChannelHandler(Controller controller, List<IsisProcess> processes) {
        this.controller = controller;
        this.processes = processes;
        ((DefaultIsisLsdb) isisLsdb).setController(this.controller);
        ((DefaultIsisLsdb) isisLsdb).setIsisInterface(isisInterfaceList());
    }

    private List<IsisInterface> isisInterfaceList() {
        List<IsisInterface> isisInterfaceList = new ArrayList<>();
        for (Integer key : isisInterfaceMap.keySet()) {
            isisInterfaceList.add(isisInterfaceMap.get(key));
        }
        return isisInterfaceList;
    }

    /**
     * Initializes the interface map with interface details.
     */
    public void initializeInterfaceMap() {
        for (IsisProcess process : processes) {
            for (IsisInterface isisInterface : process.isisInterfaceList()) {
                IsisInterface anInterface = isisInterfaceMap.get(isisInterface.interfaceIndex());
                if (anInterface == null) {
                    isisInterfaceMap.put(isisInterface.interfaceIndex(), isisInterface);
                    interfaceIps.add(isisInterface.interfaceIpAddress());
                }
            }
        }
        //Initializes the interface with all interface ip details - for ls pdu generation
        initializeInterfaceIpList();
    }

    /**
     * Updates the interface map with interface details.
     *
     * @param isisProcesses updated process instances
     */
    public void updateInterfaceMap(List<IsisProcess> isisProcesses) {
        for (IsisProcess isisUpdatedProcess : isisProcesses) {
            for (IsisInterface isisUpdatedInterface : isisUpdatedProcess.isisInterfaceList()) {
                IsisInterface isisInterface = isisInterfaceMap.get(isisUpdatedInterface.interfaceIndex());
                if (isisInterface == null) {
                    isisInterfaceMap.put(isisUpdatedInterface.interfaceIndex(), isisUpdatedInterface);
                    interfaceIps.add(isisUpdatedInterface.interfaceIpAddress());
                } else {
                    if (isisInterface.intermediateSystemName() != isisUpdatedInterface.intermediateSystemName()) {
                        isisInterface.setIntermediateSystemName(isisUpdatedInterface.intermediateSystemName());
                    }
                    if (isisInterface.reservedPacketCircuitType() != isisUpdatedInterface.reservedPacketCircuitType()) {
                        isisInterface.setReservedPacketCircuitType(isisUpdatedInterface.reservedPacketCircuitType());
                        isisInterface.removeNeighbors();
                    }
                    if (isisInterface.circuitId() != isisUpdatedInterface.circuitId()) {
                        isisInterface.setCircuitId(isisUpdatedInterface.circuitId());
                    }
                    if (isisInterface.networkType() != isisUpdatedInterface.networkType()) {
                        isisInterface.setNetworkType(isisUpdatedInterface.networkType());
                        isisInterface.removeNeighbors();
                    }
                    if (isisInterface.areaAddress() != isisUpdatedInterface.areaAddress()) {
                        isisInterface.setAreaAddress(isisUpdatedInterface.areaAddress());
                    }
                    if (isisInterface.holdingTime() != isisUpdatedInterface.holdingTime()) {
                        isisInterface.setHoldingTime(isisUpdatedInterface.holdingTime());
                    }
                    if (isisInterface.helloInterval() != isisUpdatedInterface.helloInterval()) {
                        isisInterface.setHelloInterval(isisUpdatedInterface.helloInterval());
                        isisInterface.stopHelloSender();
                        isisInterface.startHelloSender(channel);
                    }

                    isisInterfaceMap.put(isisInterface.interfaceIndex(), isisInterface);
                }
            }
        }
    }

    /**
     * Initializes the interface with all interface ip details.
     */
    public void initializeInterfaceIpList() {
        for (IsisProcess process : processes) {
            for (IsisInterface isisInterface : process.isisInterfaceList()) {
                ((DefaultIsisInterface) isisInterface).setAllConfiguredInterfaceIps(interfaceIps);
            }
        }
    }

    /**
     * Initialize channel, start hello sender and initialize LSDB.
     */
    private void initialize() {
        log.debug("IsisChannelHandler initialize..!!!");
        if (configPacket != null) {
            log.debug("IsisChannelHandler initialize -> sentConfig packet of length ::"
                              + configPacket.length);
            sentConfigPacket(configPacket);
        }
        initializeInterfaceMap();
        //start the hello timer
        startHelloSender();
        //Initialize Database
        isisLsdb.initializeDb();
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent evt) throws Exception {
        log.info("ISIS channelConnected from {}", evt.getChannel().getRemoteAddress());
        this.channel = evt.getChannel();
        initialize();
    }

    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent evt) {
        log.debug("IsisChannelHandler::channelDisconnected...!!!");
        if (controller != null) {
            controller.connectPeer();
            stopHelloSender();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        if (e.getCause() instanceof ReadTimeoutException) {
            log.debug("Disconnecting device {} due to read timeout", e.getChannel().getRemoteAddress());
            return;
        } else if (e.getCause() instanceof ClosedChannelException) {
            log.debug("Channel for ISIS {} already closed", e.getChannel().getRemoteAddress());
        } else if (e.getCause() instanceof IOException) {
            log.debug("Disconnecting ISIS {} due to IO Error: {}", e.getChannel().getRemoteAddress(),
                      e.getCause().getMessage());
        } else if (e.getCause() instanceof IsisParseException) {
            IsisParseException errMsg = (IsisParseException) e.getCause();
            byte errorCode = errMsg.errorCode();
            byte errorSubCode = errMsg.errorSubCode();
            log.debug("Error while parsing message from ISIS {}, ErrorCode {}",
                      e.getChannel().getRemoteAddress(), errorCode);
        } else if (e.getCause() instanceof RejectedExecutionException) {
            log.debug("Could not process message: queue full");
        } else {
            log.debug("Error while processing message from ISIS {}, {}",
                      e.getChannel().getRemoteAddress(), e.getCause().getMessage());
        }
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        log.debug("IsisChannelHandler::messageReceived...!!!");
        Object message = e.getMessage();
        if (message instanceof List) {
            List<IsisMessage> isisMessageList = (List<IsisMessage>) message;
            log.debug("IsisChannelHandler::List of IsisMessages Size {}", isisMessageList.size());
            if (isisMessageList != null) {
                for (IsisMessage isisMessage : isisMessageList) {
                    processIsisMessage(isisMessage, ctx);
                }
            } else {
                log.debug("IsisChannelHandler::IsisMessages Null List...!!");
            }
        }
        if (message instanceof IsisMessage) {
            IsisMessage isisMessage = (IsisMessage) message;
            log.debug("IsisChannelHandler::IsisMessages received...!!");
            processIsisMessage(isisMessage, ctx);
        }
    }

    /**
     * When an ISIS message received it is handed over to this method.
     * Based on the type of the ISIS message received it will be handed over
     * to corresponding message handler methods.
     *
     * @param isisMessage received ISIS message
     * @param ctx         channel handler context instance.
     * @throws Exception might throws exception
     */
    public void processIsisMessage(IsisMessage isisMessage, ChannelHandlerContext ctx) throws Exception {
        log.debug("IsisChannelHandler::processIsisMessage...!!!");
        int interfaceIndex = isisMessage.interfaceIndex();
        IsisInterface isisInterface = isisInterfaceMap.get(interfaceIndex);
        isisInterface.processIsisMessage(isisMessage, isisLsdb, channel);
    }

    /**
     * Starts the hello timer which sends hello packet every configured seconds.
     */
    public void startHelloSender() {
        log.debug("IsisController::startHelloSender");
        Set<Integer> interfaceIndexes = isisInterfaceMap.keySet();
        for (Integer interfaceIndex : interfaceIndexes) {
            IsisInterface isisInterface = isisInterfaceMap.get(interfaceIndex);
            isisInterface.startHelloSender(channel);
        }
    }

    /**
     * Stops the hello timer.
     */
    public void stopHelloSender() {
        log.debug("ISISChannelHandler::stopHelloTimer ");
        log.debug("IsisController::startHelloSender");
        Set<Integer> interfaceIndexes = isisInterfaceMap.keySet();
        for (Integer interfaceIndex : interfaceIndexes) {
            IsisInterface isisInterface = isisInterfaceMap.get(interfaceIndex);
            isisInterface.stopHelloSender();
        }
    }

    /**
     * Sends the interface configuration packet to server.
     *
     * @param configPacket interface configuration
     */
    public void sentConfigPacket(byte[] configPacket) {
        if (channel != null && channel.isConnected() && channel.isOpen()) {
            channel.write(configPacket);
            log.debug("IsisChannelHandler sentConfigPacket packet sent..!!!");
        } else {
            log.debug("IsisChannelHandler sentConfigPacket channel not connected - re try..!!!");
            this.configPacket = configPacket;
        }
    }
}