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

import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.timeout.ReadTimeoutException;
import org.onosproject.ofagent.api.OFSwitch;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.util.concurrent.RejectedExecutionException;

import static org.onosproject.ofagent.impl.OFChannelHandler.ChannelState.INIT;

/**
 * Implementation of OpenFlow channel handler.
 * It processes OpenFlow message according to the channel state.
 */
public final class OFChannelHandler extends ChannelDuplexHandler {

    private static final String MSG_CHANNEL_STATE = "Set channel(%s) state: %s";

    private final Logger log = LoggerFactory.getLogger(getClass());
    private final OFSwitch ofSwitch;

    private Channel channel;
    private ChannelState state;

    enum ChannelState {

        INIT {
            @Override
            void processOFMessage(final OFChannelHandler handler,
                                  final OFMessage msg) {
                logProcessOFMessageDetails(handler, msg, this);
                // TODO implement
            }
        },
        WAIT_HELLO {
            @Override
            void processOFMessage(final OFChannelHandler handler,
                                  final OFMessage msg) {
                logProcessOFMessageDetails(handler, msg, this);
                switch (msg.getType()) {
                    case HELLO:
                        handler.setState(ChannelState.WAIT_FEATURE_REQUEST);
                        break;
                    default:
                        handler.illegalMessageReceived(msg);
                        break;
                }
            }
        },
        WAIT_FEATURE_REQUEST {
            @Override
            void processOFMessage(final OFChannelHandler handler,
                                  final OFMessage msg) {
                logProcessOFMessageDetails(handler, msg, this);
                switch (msg.getType()) {
                    case FEATURES_REQUEST:
                        handler.ofSwitch.processFeaturesRequest(handler.channel, msg);
                        handler.setState(ChannelState.ESTABLISHED);
                        break;
                    case ECHO_REQUEST:
                        handler.ofSwitch.processEchoRequest(handler.channel, msg);
                        break;
                    case ERROR:
                        handler.logErrorClose((OFErrorMsg) msg);
                        break;
                    default:
                        handler.illegalMessageReceived(msg);
                        break;

                }
            }
        },
        ESTABLISHED {
            @Override
            void processOFMessage(final OFChannelHandler handler,
                                  final OFMessage msg) {
                logProcessOFMessageDetails(handler, msg, this);
                // TODO implement
                // TODO add this channel to ofSwitch role service
                switch (msg.getType()) {
                    case STATS_REQUEST:
                        //TODO implement
                        //TODO: use vNetService to build OFPortDesc.
                        handler.ofSwitch.processStatsRequest(handler.channel, msg);
                        break;
                    case SET_CONFIG:
                        //TODO implement
                        handler.ofSwitch.processSetConfigMessage(handler.channel, msg);
                        break;
                    case GET_CONFIG_REQUEST:
                        //TODO implement
                        handler.ofSwitch.processGetConfigRequest(handler.channel, msg);
                        break;
                    case BARRIER_REQUEST:
                        //TODO implement
                        handler.ofSwitch.processBarrierRequest(handler.channel, msg);
                        break;
                    case ECHO_REQUEST:
                        handler.ofSwitch.processEchoRequest(handler.channel, msg);
                        break;
                    case ROLE_REQUEST:
                        handler.ofSwitch.processRoleRequest(handler.channel, msg);
                        break;
                    case PACKET_OUT:
                        // TODO: check if this is lldp - ignore if it is not lldp
                        handler.ofSwitch.processLldp(handler.channel, msg);
                        break;
                    case FLOW_MOD:
                    case PORT_MOD:
                    case GROUP_MOD:
                    case METER_MOD:
                    case TABLE_MOD:
                        handler.ofSwitch.processControllerCommand(handler.channel, msg);
                        break;
                    case ERROR:
                        handler.logErrorClose((OFErrorMsg) msg);
                        break;
                    default:
                        handler.unhandledMessageReceived(msg);
                        break;
                }
            }
        };

        abstract void processOFMessage(final OFChannelHandler handler, final OFMessage msg);

        private static void logProcessOFMessageDetails(final OFChannelHandler handler,
                                            final OFMessage msg, ChannelState chnState) {
            handler.log.trace("Channel state: {} dpid: {} processOFMessage type: {} nsg: {}",
                              chnState, handler.ofSwitch.dpid(), msg.getType(), msg);
        }
    }

    /**
     * Default constructor.
     *
     * @param ofSwitch openflow switch that owns this channel
     */
    public OFChannelHandler(OFSwitch ofSwitch) {
        super();
        this.ofSwitch = ofSwitch;
        setState(INIT);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        this.channel = ctx.channel();
        // FIXME move this to channel handler and add channel when OF handshake is done
        ofSwitch.addControllerChannel(channel);
        try {
            ofSwitch.sendOfHello(channel);
            log.trace("Send OF_13 Hello to {}", channel.remoteAddress());
            setState(ChannelState.WAIT_HELLO);
        } catch (Exception ex) {
            log.error("Failed sending OF_13 Hello to {} for {}", channel.remoteAddress(), ex.getMessage());
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        ofSwitch.deleteControllerChannel(channel);
        log.info("Device {} disconnected from controller {}", ofSwitch.dpid(), channel.remoteAddress());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            state.processOFMessage(this, (OFMessage) msg);
        } catch (Exception ex) {
            ctx.fireExceptionCaught(ex);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        if (cause instanceof ReadTimeoutException) {
            log.error("Connection closed because of ReadTimeoutException {}", cause.getMessage());
        } else if (cause instanceof ClosedChannelException) {
            log.error("ClosedChannelException occurred");
            return;
        } else if (cause instanceof RejectedExecutionException) {
            log.error("Could not process message: queue full");
        } else if (cause instanceof IOException) {
            log.error("IOException occurred");
        } else {
            log.error("Error while processing message from switch {}", cause.getMessage());
        }
        channel.close();
    }

    private void setState(ChannelState state) {
        this.state = state;
        if (state != INIT) {
            log.debug(String.format(MSG_CHANNEL_STATE, channel.remoteAddress(), state.name()));
        }
    }

    private void logErrorClose(OFErrorMsg errorMsg) {
        log.error("{} from switch {} in state {}",
                errorMsg,
                ofSwitch.dpid(),
                state);
        channel.close();
    }

    private void illegalMessageReceived(OFMessage ofMessage) {
        log.warn("Controller should never send message {} to switch {} in current state {}",
                ofMessage.getType(), ofSwitch.dpid(), state);
    }

    private void unhandledMessageReceived(OFMessage ofMessage) {
        log.warn("Unexpected message {} received for switch {} in state {}",
                ofMessage.getType(), ofSwitch.dpid(), state);
    }
}
