/*
 * Copyright 2015-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.bgp.controller.impl;

import org.onosproject.bgp.controller.BgpCfg;
import org.onosproject.bgp.controller.BgpController;
import org.onosproject.bgp.controller.BgpId;
import org.onosproject.bgp.controller.BgpLinkListener;
import org.onosproject.bgp.controller.BgpLocalRib;
import org.onosproject.bgp.controller.BgpNodeListener;
import org.onosproject.bgp.controller.BgpPeer;
import org.onosproject.bgp.controller.BgpPeerManager;
import org.onosproject.bgp.controller.BgpRouteListener;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.BgpMessage;
import org.onosproject.bgpio.protocol.BgpUpdateMsg;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.MpReachNlri;
import org.onosproject.bgpio.types.MpUnReachNlri;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Component(immediate = true, service = BgpController.class)
public class BgpControllerImpl implements BgpController {

    private static final Logger log = LoggerFactory.getLogger(BgpControllerImpl.class);
    final Controller ctrl = new Controller(this);
    protected ConcurrentHashMap<BgpId, BgpPeer> connectedPeers = new ConcurrentHashMap<BgpId, BgpPeer>();

    protected BgpPeerManagerImpl peerManager = new BgpPeerManagerImpl();

    private BgpLocalRib bgplocalRib = new BgpLocalRibImpl(this);
    private BgpLocalRib bgplocalRibVpn = new BgpLocalRibImpl(this);

    protected Set<BgpNodeListener> bgpNodeListener = new CopyOnWriteArraySet<>();
    protected Set<BgpLinkListener> bgpLinkListener = new CopyOnWriteArraySet<>();
    protected BgpController bgpController;
    private BgpConfig bgpconfig = new BgpConfig(this);
    private List<String> activeExceptionList = new LinkedList();
    private LinkedList<String> closedExceptionList = new LinkedList<String>();
    private Map<String, List<String>> activeSessionExceptionMap = new TreeMap<>();
    private Map<String, List<String>> closedSessionExceptionMap = new TreeMap<>();
    protected Set<BgpRouteListener> bgpRouteListener = new CopyOnWriteArraySet<>();

    @Override
    public void activeSessionExceptionAdd(String peerId, String exception) {
        if (peerId != null) {
            activeExceptionList.add(exception);
            activeSessionExceptionMap.put(peerId, activeExceptionList);
        } else {
            log.debug("Peer Id is null");
        }
        if (activeExceptionList.size() > 10) {
            activeExceptionList.clear();
            activeExceptionList.add(exception);
            activeSessionExceptionMap.put(peerId, activeExceptionList);
        }
    }


    @Override
    public void closedSessionExceptionAdd(String peerId, String exception) {
        if (peerId != null) {
            closedExceptionList.add(exception);
            closedSessionExceptionMap.put(peerId, closedExceptionList);
         } else {
            log.debug("Peer Id is null");
        }
        if (closedExceptionList.size() > 10) {
            closedExceptionList.clear();
            closedExceptionList.add(exception);
            closedSessionExceptionMap.put(peerId, closedExceptionList);
        }
    }

    @Override
    public Map<String, List<String>> activeSessionMap() {
        return activeSessionExceptionMap;
    }

    @Override
    public Map<String, List<String>> closedSessionMap() {
        return closedSessionExceptionMap;
    }

    @Override
    public void addRouteListener(BgpRouteListener listener) {
        this.bgpRouteListener.add(listener);
    }

    @Override
    public void removeRouteListener(BgpRouteListener listener) {
        this.bgpRouteListener.remove(listener);
    }

    @Override
    public Set<BgpRouteListener> routeListener() {
        return bgpRouteListener;
    }

    @Activate
    public void activate() {
        this.ctrl.start();
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        activeSessionExceptionMap.clear();
        closedSessionExceptionMap.clear();
        // Close all connected peers
        closeConnectedPeers();
        this.ctrl.stop();
        log.info("Stopped");
    }

    @Override
    public Iterable<BgpPeer> getPeers() {
        return this.connectedPeers.values();
    }

    @Override
    public BgpPeer getPeer(BgpId bgpId) {
        return this.connectedPeers.get(bgpId);
    }

    @Override
    public void addListener(BgpNodeListener listener) {
        this.bgpNodeListener.add(listener);
    }

    @Override
    public void removeListener(BgpNodeListener listener) {
        this.bgpNodeListener.remove(listener);
    }

    @Override
    public Set<BgpNodeListener> listener() {
        return bgpNodeListener;
    }

    @Override
    public void writeMsg(BgpId bgpId, BgpMessage msg) {
        this.getPeer(bgpId).sendMessage(msg);
    }

    @Override
    public void processBgpPacket(BgpId bgpId, BgpMessage msg) throws BgpParseException {

        BgpPeer peer = getPeer(bgpId);

        switch (msg.getType()) {
            case OPEN:
                // TODO: Process Open message
                break;
            case KEEP_ALIVE:
                // TODO: Process keepalive message
                break;
            case NOTIFICATION:
                // TODO: Process notificatoin message
                break;
            case UPDATE:
                BgpUpdateMsg updateMsg = (BgpUpdateMsg) msg;
                List<BgpValueType> pathAttr = updateMsg.bgpPathAttributes().pathAttributes();
                if (pathAttr == null) {
                    log.debug("llPathAttr is null, cannot process update message");
                    break;
                }
                Iterator<BgpValueType> listIterator = pathAttr.iterator();
                boolean isLinkstate = false;
                boolean isEvpn = false;

                while (listIterator.hasNext()) {
                    BgpValueType attr = listIterator.next();
                    if (attr instanceof MpReachNlri) {
                        MpReachNlri mpReach = (MpReachNlri) attr;
                        if (mpReach.bgpFlowSpecNlri() == null
                                && mpReach.bgpEvpnNlri() == null) {
                            isLinkstate = true;
                        }
                        if (mpReach.bgpEvpnNlri() != null) {
                            isEvpn = true;
                        }
                    } else if (attr instanceof MpUnReachNlri) {
                        MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
                        if (mpUnReach.bgpFlowSpecNlri() == null
                                && mpUnReach.bgpEvpnNlri() == null) {
                            isLinkstate = true;
                        }
                        if (mpUnReach.bgpEvpnNlri() != null) {
                            isEvpn = true;
                        }
                    }
                }
                if (isLinkstate) {
                    peer.buildAdjRibIn(pathAttr);
                }
                if (isEvpn) {
                    for (BgpRouteListener listener : bgpRouteListener) {
                        listener.processRoute(bgpId, updateMsg);
                    }
                }
                break;
            default:
                // TODO: Process other message
                break;
        }
    }

    @Override
    public void closeConnectedPeers() {
        BgpPeer bgpPeer;
        for (BgpId id : this.connectedPeers.keySet()) {
            bgpPeer = getPeer(id);
            bgpPeer.disconnectPeer();
        }
    }

    /**
     * Implementation of an BGP Peer which is responsible for keeping track of connected peers and the state in which
     * they are.
     */
    public class BgpPeerManagerImpl implements BgpPeerManager {

        private final Logger log = LoggerFactory.getLogger(BgpPeerManagerImpl.class);
        private final Lock peerLock = new ReentrantLock();

        @Override
        public boolean addConnectedPeer(BgpId bgpId, BgpPeer bgpPeer) {

            if (connectedPeers.get(bgpId) != null) {
                this.log.error("Trying to add connectedPeer but found previous " + "value for bgp ip: {}",
                               bgpId.toString());
                return false;
            } else {
                this.log.debug("Added Peer {}", bgpId.toString());
                connectedPeers.put(bgpId, bgpPeer);
                return true;
            }
        }

        @Override
        public boolean isPeerConnected(BgpId bgpId) {
            if (connectedPeers.get(bgpId) == null) {
                this.log.error("Is peer connected: bgpIp {}.", bgpId.toString());
                return false;
            }

            return true;
        }

        @Override
        public void removeConnectedPeer(BgpId bgpId) {
            connectedPeers.remove(bgpId);
        }

        @Override
        public BgpPeer getPeer(BgpId bgpId) {
            return connectedPeers.get(bgpId);
        }

        /**
         * Gets bgp peer instance.
         *
         * @param bgpController controller instance.
         * @param sessionInfo bgp session info.
         * @param pktStats packet statistics.
         * @return BGPPeer peer instance.
         */
        public BgpPeer getBgpPeerInstance(BgpController bgpController, BgpSessionInfoImpl sessionInfo,
                                          BgpPacketStatsImpl pktStats) {
            BgpPeer bgpPeer = new BgpPeerImpl(bgpController, sessionInfo, pktStats);
            return bgpPeer;
        }

    }

    /**
     * Returns controller.
     *
     * @return controller
     */
    public Controller controller() {
        return this.ctrl;
    }

    @Override
    public ConcurrentHashMap<BgpId, BgpPeer> connectedPeers() {
        return connectedPeers;
    }

    @Override
    public BgpPeerManagerImpl peerManager() {
        return peerManager;
    }

    @Override
    public BgpCfg getConfig() {
        return this.bgpconfig;
    }

    @Override
    public int connectedPeerCount() {
        return connectedPeers.size();
    }

    /**
     * Gets the BGP local RIB.
     *
     * @return bgplocalRIB BGP local RIB.
     */
    @Override
    public BgpLocalRib bgpLocalRib() {
        return bgplocalRib;
    }

    /**
     * Gets the BGP local RIB with VPN.
     *
     * @return bgplocalRIBVpn BGP VPN local RIB .
     */
    @Override
    public BgpLocalRib bgpLocalRibVpn() {
        return bgplocalRibVpn;
    }

    @Override
    public void addLinkListener(BgpLinkListener listener) {
        this.bgpLinkListener.add(listener);
    }

    @Override
    public void removeLinkListener(BgpLinkListener listener) {
        this.bgpLinkListener.remove(listener);
    }

    @Override
    public Set<BgpLinkListener> linkListener() {
        return bgpLinkListener;
    }
}
