package org.bench4q.monitor.performance.linux;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.bench4q.monitor.model.ProcessModel;
import org.bench4q.monitor.model.ProcessModelChild;

public class ProcessMonitor {

	private List<String> instances;
	private Map<String, Double> privateBytes;
	private Map<String, Double> processorTimePercent;
	private Map<String, Double> processId;
	private Map<String, Double> virtualBytes;

	public ProcessMonitor() {
		instances = new ArrayList<String>();
		privateBytes = new HashMap<String, Double>();
		processorTimePercent = new HashMap<String, Double>();
		processId = new HashMap<String, Double>();
		virtualBytes = new HashMap<String, Double>();

	}

	public List<String> getInstances() throws IOException, InterruptedException {
		getProcessInfo(1000);
		return instances;
	}

	public double getPrivateBytes(String instance) throws IOException,
			InterruptedException {
		getProcessInfo(1000);
		return privateBytes.get(instance);

	}

	public double getProcessorTimePercent(String instance, int idleTime)
			throws IOException, InterruptedException {
		getProcessInfo(idleTime);
		return processorTimePercent.get(instance);
	}

	public double getProcessId(String instance) throws IOException,
			InterruptedException {
		getProcessInfo(1000);
		return processId.get(instance);
	}

	public double getVirtualBytes(String instance) throws IOException,
			InterruptedException {
		getProcessInfo(1000);
		return virtualBytes.get(instance);
	}

	public ProcessModel getProcessInfo(int idleTime) throws IOException,
			InterruptedException {// top鍛戒护鏄寜鐓鏉ヨ鏃剁殑

		ProcessModel processModel = new ProcessModel();
		Integer time = new Integer(idleTime / 1000);
		Runtime rt = Runtime.getRuntime();

		Process p = rt.exec("top -b -d " + time.toString() + " -n 2");
		BufferedReader in = new BufferedReader(new InputStreamReader(
				p.getInputStream()));
		String nextline;
		StringTokenizer token;
		int count = 0;
		int pid = 0, virt = 0, shr = 0, cpu = 0, command = 0;
		// int length = 0;
		while ((nextline = in.readLine()) != null) {
			if (nextline.toLowerCase().contains("pid user"))
				count++;
			if (count == 2 && nextline.toLowerCase().contains("pid user")) {
				token = new StringTokenizer(nextline);
				int i = 0;
				while (token.hasMoreTokens()) {
					String str = token.nextToken();
					if (str.equals("PID"))
						pid = i;
					if (str.equals("VIRT"))
						virt = i;
					if (str.equals("SHR"))
						shr = i;
					if (str.equals("%CPU"))
						cpu = i;
					if (str.equals("COMMAND"))
						command = i;
					i++;
				}
				// length = i;
				nextline = in.readLine();

			}

			if (count == 2 && nextline.length() > 0) {

				String s[] = new String[20];
				token = new StringTokenizer(nextline);
				for (int i = 0; token.hasMoreTokens(); i++) {
					s[i] = token.nextToken();
				}
				String instance = s[command];
				instances.add(s[command]);
				double virtValue, shrValue;
				if (s[virt].contains("m")) {
					s[virt] = s[virt].substring(0, s[virt].length() - 1);
					virtValue = Double.parseDouble(s[virt]) * 1024;

				} else
					virtValue = Double.parseDouble(s[virt]);
				if (s[shr].contains("m")) {
					s[shr] = s[shr].substring(0, s[shr].length() - 1);
					shrValue = Double.parseDouble(s[shr]) * 1024;
				} else
					shrValue = Double.parseDouble(s[shr]);
				double pbytes = virtValue - shrValue;
				privateBytes.put(instance, pbytes);
				processorTimePercent.put(instance, Double.parseDouble(s[cpu]));
				processId.put(instance, Double.parseDouble(s[pid]));
				virtualBytes.put(instance, virtValue);
			}
		}

		in.close();
		// System.out.println(instances.size());
		Iterator<String> itr = instances.iterator();
		while (itr.hasNext()) {
			ProcessModelChild processModelChild = new ProcessModelChild();
			String instance = itr.next();
			processModelChild.setInstanceString(instance);
			processModelChild.setPrivateBytes(privateBytes.get(instance));
			processModelChild.setProcessId(processId.get(instance));
			processModelChild.setProcessorTimePercent(processorTimePercent
					.get(instance));
			processModelChild.setVirtualBytes(virtualBytes.get(instance));
			processModel.getProcesModelList().add(processModelChild);
		}
		return processModel;
	}

}