package org.bench4q.monitor.performance.linux;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.bench4q.monitor.entiry.LinuxFileRead;
import org.bench4q.monitor.model.ProcessorModel;
import org.bench4q.monitor.model.ProcessorModelChild;

public class ProcessorMonitor extends LinuxFileRead {

	private List<String> instances;

	private Map<String, Double> privilegedTimePercent;
	private Map<String, Double> processorTimePercent;
	private Map<String, Double> userTimePercent;

	public void setInstances(List<String> instances) {
		this.instances = instances;
	}

	public Map<String, Double> getPrivilegedTimePercent() {
		return privilegedTimePercent;
	}

	public void setPrivilegedTimePercent(
			Map<String, Double> privilegedTimePercent) {
		this.privilegedTimePercent = privilegedTimePercent;
	}

	public Map<String, Double> getProcessorTimePercent() {
		return processorTimePercent;
	}

	public void setProcessorTimePercent(Map<String, Double> processorTimePercent) {
		this.processorTimePercent = processorTimePercent;
	}

	public Map<String, Double> getUserTimePercent() {
		return userTimePercent;
	}

	public void setUserTimePercent(Map<String, Double> userTimePercent) {
		this.userTimePercent = userTimePercent;
	}

	public ProcessorMonitor() throws FileNotFoundException {
		super("/proc/stat");
		this.instances = new ArrayList<String>();
		this.privilegedTimePercent = new HashMap<String, Double>();
		this.processorTimePercent = new HashMap<String, Double>();
		this.userTimePercent = new HashMap<String, Double>();
	}

	public List<String> getInstances() throws IOException, InterruptedException {
		BufferedReader br = this.getBufferedReader();

		StringTokenizer token = new StringTokenizer(br.readLine());

		while (token != null) {
			String instance;
			instance = token.nextToken().toLowerCase();
			if (!instance.contains("cpu"))
				break;
			this.instances.add(instance);

			token = new StringTokenizer(br.readLine());
		}
		br.close();
		return this.instances;
	}

	public double getPrivilegedTimePercent(String instance, int idleTime)
			throws IOException, InterruptedException {

		getProcessorInfo(idleTime);
		return privilegedTimePercent.get(instance);

	}

	public double getProcessorTimePercent(String instance, int idleTime)
			throws IOException, InterruptedException {

		getProcessorInfo(idleTime);
		return processorTimePercent.get(instance);
	}

	public double getUserTimePercent(String instance, int idleTime)
			throws IOException, InterruptedException {

		getProcessorInfo(idleTime);
		return userTimePercent.get(instance);
	}

	public ProcessorModel getProcessorInfo(int idleTime) throws IOException,
			InterruptedException {
		ProcessorModel processorModel = new ProcessorModel();
		BufferedReader br = this.getBufferedReader();
		Map<String, StringTokenizer> tokens = new HashMap<String, StringTokenizer>();
		StringTokenizer token = new StringTokenizer(br.readLine());
		// int i = 0;
		while (token != null) {

			String instance = token.nextToken().toLowerCase();
			if (instance.contains("cpu")) {
				this.instances.add(instance);
				tokens.put(instance, token);
				// i++;
				token = new StringTokenizer(br.readLine());
			} else
				break;
		}
		br.close();
		Thread.sleep(idleTime);
		File file = new File("/proc/stat");
		br = new BufferedReader(
				new InputStreamReader(new FileInputStream(file)));
		String str;
		int user1, user2 = 0, nice1, nice2 = 0, sys1, sys2 = 0, idle1, idle2 = 0, iowait1, iowait2 = 0;

		while ((str = br.readLine()) != null) {
			token = new StringTokenizer(str);
			String instance = token.nextToken().toLowerCase();
			if (instance.contains("cpu")) {
				user2 = Integer.parseInt(token.nextToken());
				nice2 = Integer.parseInt(token.nextToken());
				sys2 = Integer.parseInt(token.nextToken());
				idle2 = Integer.parseInt(token.nextToken());
				iowait2 = Integer.parseInt(token.nextToken());
				token = tokens.get(instance);
				// token.nextToken();
				user1 = Integer.parseInt(token.nextToken());
				nice1 = Integer.parseInt(token.nextToken());
				sys1 = Integer.parseInt(token.nextToken());
				idle1 = Integer.parseInt(token.nextToken());
				iowait1 = Integer.parseInt(token.nextToken());
				Double processorTimePercent_temp = (double) ((user2 + sys2 + nice2) - (user1
						+ sys1 + nice1))
						/ (double) ((user2 + sys2 + idle2 + nice2 + iowait2) - (user1
								+ sys1 + idle1 + nice1 + iowait1)) * 100;
				if(processorTimePercent_temp.equals("NaN"))  processorTimePercent_temp=0.0;
				Double userTimePercent_temp = (double) ((user2) - (user1))
						/ (double) ((user2 + sys2 + nice2 + idle2 + iowait2) - (user1
								+ sys1 + iowait1 + nice1 + idle1)) * 100;
				if(userTimePercent_temp.equals("NaN"))	userTimePercent_temp=0.0;
				Double privilegedTimePercent_temp = (double) ((sys2) - (sys1))
						/ (double) ((user2 + sys2 + nice2 + idle2 + iowait2) - (user1
								+ sys1 + iowait1 + nice1 + idle2)) * 100;
				if(privilegedTimePercent_temp.equals("NaN")) privilegedTimePercent_temp=0.0;
				privilegedTimePercent.put(instance, privilegedTimePercent_temp);
				processorTimePercent.put(instance, processorTimePercent_temp);
				userTimePercent.put(instance, userTimePercent_temp);
				ProcessorModelChild processorModelChild = new ProcessorModelChild();
				processorModelChild.setInstance(instance);
				processorModelChild
						.setPrivilegedTimePercent(privilegedTimePercent_temp);
				processorModelChild
						.setProcessorTimePercent(processorTimePercent_temp);
				processorModelChild.setUserTimePercent(userTimePercent_temp);
				processorModel.getProcessorModelList().add(processorModelChild);
			} else
				break;
		}

		br.close();
		return processorModel;

	}

}
