package org.inria.bmajwatcher.server.data;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.inria.biomaj.session.bank.BiomajSQLQuerier;
import org.inria.biomaj.session.bank.ProductionDirectory;
import org.inria.biomaj.sql.SQLConnection;
import org.inria.biomaj.sql.SQLConnectionFactory;
import org.inria.biomaj.utils.BiomajUtils;
import org.inria.bmajwatcher.server.UserManagerServiceImpl;
import org.inria.bmajwatcher.server.utils.Utils;

/**
 * Queries the database via biomaj to retrieve banks data used
 * to build statistics.
 * 
 * 
 * @author rsabas
 *
 */
public class StatsRetriever {
	
	private static Logger log = Logger.getLogger(StatsRetriever.class);

	public static List<Map<String, String>> getBankStats(String bankName, int max) {
		/*
		 * Retrieve :
		 *  - File count (download + online + offline)
		 *  - bandwidth
		 *  - size
		 *  - Duration
		 *  - File turnover
		 */
		List<Map<String, String>> res = new ArrayList<Map<String,String>>();
		
		
		String query = "SELECT session FROM productionDirectory WHERE ref_idbank=" +
				"(SELECT idbank FROM bank WHERE name='" + bankName + "') " +
				"ORDER BY creation DESC";
		
		SQLConnection mainC = SQLConnectionFactory.getConnection();
		Statement mainS = mainC.getStatement();
		ResultSet mainRs = mainC.executeQuery(query, mainS);
		
		SQLConnection connection = SQLConnectionFactory.getConnection();
		Statement stat = connection.getStatement();
		
		int count = 0;
		
		try {
			while (mainRs.next()) {
				if (max > 0 && count++ >= max) {
					break;
				}
				
				long session = mainRs.getLong(1);
				
				Map<String, String> content = new HashMap<String, String>();
				
				query = "SELECT sizeRelease FROM updateBank WHERE idupdateBank=" +
						"(SELECT ref_idupdateBank FROM session WHERE idsession=" + session + ")";
				ResultSet rs = connection.executeQuery(query, stat);
				double size;
				try {
					if (rs.next()) {
						size = (double) BiomajUtils.stringToSize(rs.getString(BiomajSQLQuerier.SIZE_RELEASE)) / 1000000;
					} else {
						continue;
					}
				} catch (SQLException e) {
					e.printStackTrace();
					continue;
				}
				
				query = "SELECT * FROM sessionTask WHERE idsessionTask IN " +
						"(SELECT ref_idsessionTask FROM session_has_sessionTask WHERE ref_idsession=" + session + ") " +
						"AND (taskType='check' OR taskType='download')";
				rs = connection.executeQuery(query, stat);
				
				float bandwidth = 0;
				int totalFiles = 0;
				int existingFiles = 0;
				try {
					while (rs.next()) {
						String taskType = rs.getString(BiomajSQLQuerier.TASK_TYPE);
					
						if (taskType.equals("download")) { // Get bandwidth
							bandwidth = rs.getFloat(BiomajSQLQuerier.BANDWIDTH);
						} else if (taskType.equals("check")) { // dl
							existingFiles = rs.getInt(BiomajSQLQuerier.NB_LOCAL_ONLINE_FILES);
							totalFiles = rs.getInt(BiomajSQLQuerier.NB_DOWNLOADED_FILES) +
								rs.getInt(BiomajSQLQuerier.NB_LOCAL_OFFLINE_FILES) +
								existingFiles;
							
						}
					}
				} catch (SQLException e) {
					e.printStackTrace();
					continue;
				}
				
				String time = "";
				String duration = "";
				query = "SELECT * FROM session WHERE idsession=" + session;
				rs = connection.executeQuery(query, stat);
				try {
					if (rs.next()) {
						time = String.valueOf(rs.getTimestamp(BiomajSQLQuerier.SESSION_START).getTime());
						duration = String.valueOf((int) (rs.getTimestamp(BiomajSQLQuerier.SESSION_END).getTime() - rs.getTimestamp(BiomajSQLQuerier.SESSION_START).getTime()) / 1000);
					} else {
						continue;
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				content.put("size", String.valueOf(size));
				content.put("bandwidth", String.valueOf(bandwidth));
				if (totalFiles == 0) {
					content.put("turnover", "0");
				} else {
					content.put("turnover", String.valueOf(100 - ((existingFiles * 100) / totalFiles)));
				}
				content.put("totalfiles", String.valueOf(totalFiles));
				content.put("time", time);
				content.put("duration", duration);
				
				
				boolean added = false;
				for (int i = 0; i < res.size(); i++) {
					if (Long.valueOf(res.get(i).get("time")) > Long.valueOf(time)) {
						res.add(i, content);
						added = true;
						break;
					}
				}
				if (!added) { // add at the end
					res.add(content);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		SQLConnectionFactory.closeConnection(mainS);
		SQLConnectionFactory.closeConnection(stat);
		return res;
		
	}
	
	
	/**
	 * Returns for each bank in the database its name, type,
	 * size and server.
	 * 
	 * @return
	 */
	public static List<Map<String, String>> getBanksSize(String userKey) {
		
		String query = "SELECT name FROM bank WHERE ref_iduser IN " +
				"(SELECT ref_iduser FROM bw_user_has_group WHERE ref_idgroup IN " +
				"(SELECT ref_idgroup FROM bw_user_has_group WHERE ref_iduser=" +
				"(SELECT iduser FROM bw_user WHERE auth_key='" + userKey + "')))";
		
		
		boolean admin = false;
		if (admin = UserManagerServiceImpl.isAdminKey(userKey)) {
			query = "SELECT name FROM bank";
		}
		
		if (userKey == null)
			query = "SELECT name FROM bank WHERE visibility=true";
		
		List<Map<String, String>> res = new ArrayList<Map<String,String>>();
		
		SQLConnection connection = SQLConnectionFactory.getConnection();
		Statement stat = connection.getStatement();
		
		ResultSet rs = connection.executeQuery(query, stat);
		try {
			while (rs.next()) {
				
				String bank = rs.getString(1);
				
				List<ProductionDirectory> dirs = BiomajSQLQuerier.getAvailableProductionDirectories(bank);
				if (dirs.size() == 0)
					continue;
				
				long size = 0;
				for (ProductionDirectory dir : dirs)
					size += dir.getSize();
				
//				Map<String, String> map = BiomajSQLQuerier.getBankInfo(bank);
				SQLConnection c2 = SQLConnectionFactory.getConnection();
				Statement s2 = c2.getStatement();
				query = "SELECT dbType,server FROM remoteInfo WHERE idremoteInfo=" +
						"(SELECT max(ref_idremoteInfo) FROM configuration WHERE ref_idbank=" +
						"(SELECT idbank FROM bank WHERE name='" + bank + "'))";
				ResultSet rs2 = c2.executeQuery(query, s2);
				if (rs2.next()) {
					Map<String, String> info = new HashMap<String, String>();
					info.put("name", bank);
					info.put("size", Utils.byteToMB(size));
					info.put("type", rs2.getString(BiomajSQLQuerier.DB_TYPE));
					info.put("server", rs2.getString(BiomajSQLQuerier.SERVER));
					
					if (admin) {
						query = "SELECT login FROM bw_user WHERE iduser=" +
								"(SELECT ref_iduser FROM bank WHERE name='" + bank + "')";
						rs2 = c2.executeQuery(query, s2);
						if (rs2.next()) {
							info.put("owner", rs2.getString(1));
						}
					}
					res.add(info);
				}
				SQLConnectionFactory.closeConnection(s2);
			}
			Map<String, String> freeSpace = new HashMap<String, String>();
			freeSpace.put("name", "Free space");
			freeSpace.put("size", String.valueOf(Utils.byteToGB(BiomajUtils.getFreeSize())));
			freeSpace.put("type", "");
			freeSpace.put("server", "");
			res.add(freeSpace);
		} catch (SQLException ex) {
			log.error(ex);
		}
		
		SQLConnectionFactory.closeConnection(stat);
		
		return res;
	}
	
	
}
