// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)

// 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 eu.teraflow.tid.bgp4Peer.management;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Inet4Address;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Hashtable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import eu.teraflow.tid.bgp4Peer.bgp4session.BGP4SessionsInformation;
import eu.teraflow.tid.bgp4Peer.peer.SendTopology;
import eu.teraflow.tid.bgp4Peer.tedb.IntraTEDBS;
import eu.teraflow.tid.tedb.DomainTEDB;
import eu.teraflow.tid.tedb.MultiDomainTEDB;
import eu.teraflow.tid.tedb.SimpleTEDB;
import eu.teraflow.tid.tedb.TEDB;

/**
 * 
 * @author mcs
 *
 */
public class BGP4ManagementSession extends Thread {
	/**
	 * The socket of the management session
	 */
	private Socket socket;
	
	/**
	 * Logger
	 */
	private Logger log;
	
	/**
	 * Output Stream of the managament session, to write the answers.
	 */
	private PrintStream out;
	/**
	 * Topology database for interDomain Links.
	 */
	private MultiDomainTEDB multiTEDB;
	/**
	 * Topology database for intradomain Links. It owns several domains.
	 */
	private Hashtable<String,TEDB> intraTEDBs;
	
	/**
	 * The infomation of all the active sessions
	 */
	private BGP4SessionsInformation bgp4SessionsInformation;
	/**
	 * Class to send the topology. It is needes to set the parameters sendTopology to true or false.
	 */
	private SendTopology sendTopology;
	
	public BGP4ManagementSession(Socket s,MultiDomainTEDB multiTEDB, Hashtable<String,TEDB> intraTEDBs,BGP4SessionsInformation bgp4SessionsInformation, SendTopology sendTopology){
		this.socket=s;
		log=LoggerFactory.getLogger("BGP4Server");
		this.multiTEDB=multiTEDB;
		this.intraTEDBs=intraTEDBs;
		this.bgp4SessionsInformation= bgp4SessionsInformation;
		this.sendTopology=sendTopology;
	}
	
	public void run(){
		log.info("Starting Management session");
		boolean running=true;
		try {
			out=new PrintStream(socket.getOutputStream());
		} catch (IOException e) {
			log.warn("Management session cancelled: "+e.getMessage());
			return;
		}
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			while (running) {
				//out.print("BGP4:>");
				
				
				
				out.print("Available commands:\r\n");
				out.print(" > show topology\r\n");
				out.print(" > show sessions\r\n");
				out.print(" > set traces on\r\n");
				out.print(" > set traces off\r\n");
				out.print(" > send topology on\r\n");
				out.print(" > send topology off\r\n");
				out.print(" > quit\r\n");
				
				
				String command = null;
				try {
					command = br.readLine();
				} catch (IOException ioe) {
					log.warn("IO error trying to read your command");
					return;
				}
				if (command.equals("quit")) {
					log.info("Ending Management Session");
					out.println("bye!");
					try {
						out.close();						
					} catch (Exception e){
						e.printStackTrace();
					}
					try {
						br.close();						
					} catch (Exception e){
						e.printStackTrace();
					}					
					return;
				}				
				
//				else if (command.equals("help")){
//					out.print("Available commands:\r\n");
//					out.print(" > show topology\r\n");
//					out.print(" > show sessions\r\n");
//					out.print(" > set traces on\r\n");
//					out.print(" > set traces off\r\n");
//					out.print(" > send topology on\r\n");
//					out.print(" > send topology off\r\n");
//					out.print(" > quit\r\n");
//					
//				}
				else if (command.equals("show sessions")){
					//Print intradomain and interDomain links
					out.print(bgp4SessionsInformation.toString());
				}
				else if (command.equals("show topology")){
					//Print intradomain and interDomain links
					if (multiTEDB != null)
						out.println(multiTEDB.printTopology());
					Enumeration<String> domainTedbs=intraTEDBs.keys();
					while (domainTedbs.hasMoreElements()){		
						String domainID=domainTedbs.nextElement();
						TEDB ted=intraTEDBs.get(domainID);
						if (ted instanceof DomainTEDB) {
							out.println("Intradomain TEDB with ID "+domainID);
							out.println(ted.printTopology());
						}
						
					}
					
				}
				else if (command.equals("set traces on")) {
					//log.setLevel(Level.ALL);		
					Logger log2=LoggerFactory.getLogger("BGP4Parser");
					//log2.setLevel(Level.ALL);			
					Logger log3=LoggerFactory.getLogger("BGP4Client");
					//log3.setLevel(Level.ALL);
					out.print("traces on!\r\n");
				} 
				else if (command.equals("set traces off")) {
					//log.setLevel(Level.SEVERE);		
					Logger log2=LoggerFactory.getLogger("BGP4Parser");
					//log2.setLevel(Level.SEVERE);
					Logger log3=LoggerFactory.getLogger("BGP4Client");
					//log3.setLevel(Level.SEVERE);
					out.print("traces off!\r\n");
				} 
				else if (command.equals("send topology on")) {
					sendTopology.setSendTopology(true);
				}
				else if (command.equals("send topology off")) {
					sendTopology.setSendTopology(false);
				}
				else{
					out.print("invalid command\n");	
					out.print("\n");
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
	}
}
