package org.bench4q.monitor.performance.linux;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

import org.bench4q.monitor.entiry.LinuxFileRead;
import org.bench4q.monitor.model.MemoryModel;

public class MemoryMonitor extends LinuxFileRead {
	// /proc/meminfo
	private double cacheBytes = 0;

	public double getCacheBytes() {
		return cacheBytes;
	}

	public void setCacheBytes(double cacheBytes) {
		this.cacheBytes = cacheBytes;
	}

	public double getCommittedBytes() {
		return committedBytes;
	}

	public void setCommittedBytes(double committedBytes) {
		this.committedBytes = committedBytes;
	}

	public double getAvailableKiloBytes() {
		return availableKiloBytes;
	}

	public void setAvailableKiloBytes(double availableKiloBytes) {
		this.availableKiloBytes = availableKiloBytes;
	}

	public double getPagesPerSecond() {
		return pagesPerSecond;
	}

	public void setPagesPerSecond(double pagesPerSecond) {
		this.pagesPerSecond = pagesPerSecond;
	}

	public double getPagesInputPerSecond() {
		return pagesInputPerSecond;
	}

	public void setPagesInputPerSecond(double pagesInputPerSecond) {
		this.pagesInputPerSecond = pagesInputPerSecond;
	}

	public double getPagesOutputPerSecond() {
		return pagesOutputPerSecond;
	}

	public void setPagesOutputPerSecond(double pagesOutputPerSecond) {
		this.pagesOutputPerSecond = pagesOutputPerSecond;
	}

	private double committedBytes = 0;
	private double availableKiloBytes = 0;

	private double pagesPerSecond = 0;// (k)
	private double pagesInputPerSecond = 0;
	private double pagesOutputPerSecond = 0;

	public MemoryMonitor() throws FileNotFoundException {
		super("/proc/meminfo");
	}

	public MemoryModel getMemoryInfo(int idleTime) throws IOException {
		MemoryModel memoryModel = new MemoryModel();
		Runtime rt = Runtime.getRuntime();
		String time = new Integer(idleTime / 1000).toString();
		Process p = rt.exec("vmstat " + time + " 2");
		BufferedReader in = new BufferedReader(new InputStreamReader(
				p.getInputStream()));
		StringTokenizer token;
		String str = in.readLine();
		str = in.readLine();
		int si = 0, so = 0;
		token = new StringTokenizer(str);
		for (int i = 0;; i++) {
			str = token.nextToken().toLowerCase();
			if (str.contains("si")) {
				si = i;
			}
			if (str.contains("so")) {
				so = i;
			}
			if (!(token.hasMoreTokens()))
				break;

		}
		str = in.readLine();
		str = in.readLine();
		token = new StringTokenizer(str);
		for (int i = 0;; i++) {
			str = token.nextToken().toLowerCase();
			if (i == si)
				pagesInputPerSecond = Integer.parseInt(str);
			if (i == so)
				pagesOutputPerSecond = Integer.parseInt(str);
			if (!(token.hasMoreTokens()))
				break;
		}

		pagesPerSecond = pagesInputPerSecond + pagesOutputPerSecond;

		BufferedReader br = this.getBufferedReader();

		while ((str = br.readLine()) != null) {
			token = new StringTokenizer(str);
			if (!token.hasMoreTokens())
				continue;

			str = token.nextToken();
			if (!token.hasMoreTokens())
				continue;

			if (str.equalsIgnoreCase("Cached:"))
				cacheBytes = Integer.parseInt(token.nextToken()) * 1024;
			else if (str.equalsIgnoreCase("MemFree:"))
				availableKiloBytes = Integer.parseInt(token.nextToken());
			else if (str.equalsIgnoreCase("Committed_AS:"))
				committedBytes = Integer.parseInt(token.nextToken()) * 1024;
		}
		memoryModel.setAvailableKiloBytes(availableKiloBytes);
		memoryModel.setCacheBytes(cacheBytes);
		memoryModel.setCommittedBytes(committedBytes);
		memoryModel.setPagesInputPerSecond(pagesInputPerSecond);
		memoryModel.setPagesOutputPerSecond(pagesOutputPerSecond);
		memoryModel.setPagesPerSecond(pagesPerSecond);
		return memoryModel;
	}

}
