package org.bench4q.monitor.model;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

import org.apache.log4j.Logger;
import org.bench4q.monitor.service.GetSigar;
import org.bench4q.monitor.service.GetThreadPool;
import org.hyperic.sigar.ProcState;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;

import com.google.gson.annotations.Expose;

@XmlRootElement
public class ProcessModel implements Runnable {
	private Sigar sigar = GetSigar.getSigar();
	@Expose
	private List<ProcessModelChild> processModelList;
	@Expose
	private long[] processPids;
	@Expose
	private List<String> processNameList;
	@Expose
	private int size;

	public static void main(String args[]) throws SigarException,
			InterruptedException, ExecutionException {
		long time = System.currentTimeMillis();
		ProcessModel processModel = new ProcessModel();
		System.out.println("total process:"
				+ processModel.getProcessPids().length);
		for (int i = 0; i < processModel.getProcessPids().length; i++) {
			if (processModel.getProcessModelList().get(i) != null) {

				System.out.println("pid:"
						+ processModel.getProcessModelList().get(i)
								.getInstanceString());
				System.out.println("name:"
						+ processModel.getProcessModelList().get(i)
								.getProcessId());
				System.out.println("cpu percent:"
						+ processModel.getProcessModelList().get(i)
								.getProcessorTimePercent());
				System.out.println("getResidentKBytes:"
						+ processModel.getProcessModelList().get(i)
								.getResidentKBytes());
				System.out.println("virtural Kbytes:"
						+ processModel.getProcessModelList().get(i).getVSize());
				System.out.println(" Kbytes:"
						+ processModel.getProcessModelList().get(i)
								.getMemSize());
				break;

			}

		}

		System.out.println(System.currentTimeMillis() - time);

	}

	private MonitorMain monitorMain;
	private Logger logger = Logger.getLogger(ProcessModel.class);

	public ProcessModel(MonitorMain monitorMain) {
		this.monitorMain = monitorMain;
	}

	public void run() {
		try {
			monitorMain.setProcesssModel(new ProcessModel());
		} catch (SigarException e) {
			// TODO Auto-generated catch block
			logger.info(e, e.fillInStackTrace());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			logger.info(e, e.fillInStackTrace());
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			logger.info(e, e.fillInStackTrace());
		}

	}

	public ProcessModel() throws SigarException, InterruptedException,
			ExecutionException {
		this.setProcessPids();
		this.setProcesModelList();
		this.setProcessNameList();
		this.setSize();
	}

	@XmlElement
	public int getSize() {
		return this.size;
	}

	private void setSize() throws SigarException {
		this.size = sigar.getProcList().length;
	}

	@XmlElementWrapper()
	@XmlElement(type = ProcessModelChild.class)
	public List<ProcessModelChild> getProcessModelList() {
		return processModelList;
	}

	public void setProcesModelList() throws SigarException,
			InterruptedException, ExecutionException {
		this.processModelList = new ArrayList<ProcessModelChild>();
		List<Future<ProcessModelChild>> futures = new ArrayList<Future<ProcessModelChild>>();
		for (int i = 0; i < this.processPids.length; ++i) {
			try {
				futures.add(GetThreadPool.getExecutorService().submit(
						new NewProcessChild(processPids[i],
								new ProcessSigarReleatedModel(processPids[i]))));
			} catch (SigarException e) {
				processModelList.add(new ProcessModelChild(processPids[i]));
			}
		}
		for (Future<ProcessModelChild> future : futures) {
			processModelList.add(future.get());
		}

	}

	@XmlElement
	public long[] getProcessPids() {
		return processPids;
	}

	private void setProcessPids() throws SigarException {
		this.processPids = sigar.getProcList();
	}

	@XmlElementWrapper(name = "processNameList")
	@XmlElement(name = "processName", type = String.class)
	public List<String> getProcessNameList() {
		return processNameList;
	}

	private void setProcessNameList() throws SigarException {
		this.processNameList = new ArrayList<String>();
		for (long pid : this.getProcessPids()) {
			try {
				ProcState procState = sigar.getProcState(pid);
				processNameList.add(procState.getName());
			} catch (SigarException e) {
			}
		}
	}

}

class NewProcessChild implements Callable<ProcessModelChild> {
	private long pid;
	private ProcessSigarReleatedModel processSigarReleatedModel;

	public NewProcessChild(long pid,
			ProcessSigarReleatedModel processSigarReleatedModel) {
		this.pid = pid;
		this.processSigarReleatedModel = processSigarReleatedModel;
	}

	public ProcessModelChild call() {
		try {
			return new ProcessModelChild(pid, processSigarReleatedModel);
		} catch (SigarException e) {
			return new ProcessModelChild(pid);
		}
	}
}