// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 com.cloud.consoleproxy;

import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
 * 
 * @author Kelven Yang
 * ConsoleProxyClientStatsCollector collects client stats for console proxy agent to report
 */
public class ConsoleProxyClientStatsCollector {
	
	ArrayList<ConsoleProxyConnection> connections;
	
	public ConsoleProxyClientStatsCollector() {
	}
	
	public ConsoleProxyClientStatsCollector(Hashtable<String, ConsoleProxyClient> connMap) {
		setConnections(connMap);
	}
	
	public String getStatsReport() {
		Gson gson = new GsonBuilder().setPrettyPrinting().create();
		return gson.toJson(this);
	}
	
	public void getStatsReport(OutputStreamWriter os) {
		Gson gson = new GsonBuilder().setPrettyPrinting().create();
		gson.toJson(this, os);
	}

	private void setConnections(Hashtable<String, ConsoleProxyClient> connMap) {
		
		ArrayList<ConsoleProxyConnection> conns = new ArrayList<ConsoleProxyConnection>();
		Enumeration<String> e = connMap.keys();
	    while (e.hasMoreElements()) {
	    	synchronized (connMap) {
	    		String key = e.nextElement();
		        ConsoleProxyClient client = connMap.get(key);
		         
		        ConsoleProxyConnection conn = new ConsoleProxyConnection();
		         
		        conn.id = client.getClientId();
		        conn.clientInfo = "";
		        conn.host = client.getClientHostAddress();
		        conn.port = client.getClientHostPort();
		        conn.tag = client.getClientTag();
		        conn.createTime = client.getClientCreateTime();
		        conn.lastUsedTime = client.getClientLastFrontEndActivityTime();
		        conns.add(conn);
	    	}
	    }
	    connections = conns;
	}
	
	public static class ConsoleProxyConnection {
		public int id;
		public String clientInfo;
		public String host;
		public int port;
		public String tag;
		public long createTime;
		public long lastUsedTime;
		
		public ConsoleProxyConnection() {
		}
	}
}
