package org.bench4q.monitor.performance.linux;

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

import org.bench4q.monitor.entiry.LinuxFileRead;
import org.bench4q.monitor.model.PhysicalDiskModel;
import org.bench4q.monitor.model.PhysicalDiskModelChild;

public class PhysicalDiskMonitor extends LinuxFileRead {
	public PhysicalDiskMonitor() throws FileNotFoundException {
		super("/proc/diskstats");
		instance = new ArrayList<String>();
		diskTimePercent = new HashMap<String, Double>();
		averageDiskQueueLength = new HashMap<String, Double>();
		currentDiskQueueLength = new HashMap<String, Double>();
		diskReadBytesPerSecond = new HashMap<String, Double>();
		diskWriteBytesPerSecond = new HashMap<String, Double>();
		diskBytesPerSecond = new HashMap<String, Double>();
	}

	private List<String> instance;
	private Map<String, Double> diskTimePercent;
	private Map<String, Double> averageDiskQueueLength;
	private Map<String, Double> currentDiskQueueLength;
	private Map<String, Double> diskReadBytesPerSecond;
	private Map<String, Double> diskWriteBytesPerSecond;
	private Map<String, Double> diskBytesPerSecond;

	public List<String> getInstances() throws IOException, InterruptedException {
		this.getPhysicalDiskInfo(1);
		return this.instance;
	}

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

		this.getPhysicalDiskInfo(idleTime);
		return this.diskTimePercent.get(instance);
	}

	public double getAverageDiskQueueLength(String instance, int idleTime)
			throws IOException, InterruptedException {
		this.getPhysicalDiskInfo(idleTime);
		return this.averageDiskQueueLength.get(instance);
	}

	public double getCurrentDiskQueueLength(String instance)
			throws IOException, InterruptedException {
		this.getPhysicalDiskInfo(1);
		return this.currentDiskQueueLength.get(instance);

	}

	public double getReadBytesPerSecond(String instance, int idleTime)
			throws IOException, InterruptedException {
		this.getPhysicalDiskInfo(idleTime);
		return this.diskReadBytesPerSecond.get(instance);
	}

	public double getDiskWriteBytesPerSecond(String instance, int idleTime)
			throws IOException, InterruptedException {
		this.getPhysicalDiskInfo(idleTime);
		return this.diskWriteBytesPerSecond.get(instance);
	}

	public double getDiskBytesPerSecond(String instance, int idleTime)
			throws IOException, InterruptedException {
		this.getPhysicalDiskInfo(idleTime);
		return this.diskBytesPerSecond.get(instance);
	}

	public PhysicalDiskModel getPhysicalDiskInfo(int idleTime)
			throws IOException, InterruptedException {

		Runtime rt = Runtime.getRuntime();
		Integer time = new Integer(idleTime);
		Process p = rt.exec("iostat -x " + time.toString() + " 2");// df -hl
																	// 查看硬盘空间

		BufferedReader in = new BufferedReader(new InputStreamReader(
				p.getInputStream()));
		String str = "";
		int j = 0;
		while ((str = in.readLine()) != null) {
			if (str.contains("Device"))
				j++;
			if (j == 2)
				break;
		}
		int device = 0, rkb = 0, wkb = 0, avgqu = 0, util = 0;
		StringTokenizer token = new StringTokenizer(str.toLowerCase());
		int i = 0;
		while (token.hasMoreTokens()) {

			str = token.nextToken();

			if (str.contains("device"))
				device = i;
			if (str.contains("rkb/s"))
				rkb = i;
			if (str.contains("wkb/s"))
				wkb = i;
			if (str.contains("avgqu-sz"))
				avgqu = i;
			if (str.contains("%util"))
				util = i;
			i++;
		}

		while ((str = in.readLine()) != null) {
			i = 0;
			token = new StringTokenizer(str);
			String elem = "";
			while (token.hasMoreTokens()) {
				str = token.nextToken();

				if (device == i) {
					instance.add(str);
					elem = str;
				}
				if (rkb == i) {
					diskReadBytesPerSecond.put(elem,
							(Double.parseDouble(str)) * 1024);
				}
				if (wkb == i) {
					diskWriteBytesPerSecond.put(elem,
							(Double.parseDouble(str)) * 1024);
					System.out.println(str);
				}
				if (avgqu == i) {
					averageDiskQueueLength.put(elem, (Double.parseDouble(str)));
				}

				if (util == i)
					diskTimePercent.put(elem, Double.parseDouble(str));
				i++;
			}

		}
		Set<String> set = diskReadBytesPerSecond.keySet();
		Iterator<String> itr = set.iterator();
		while (itr.hasNext()) {
			String elem = itr.next();
			diskBytesPerSecond.put(elem, diskReadBytesPerSecond.get(elem)
					+ diskWriteBytesPerSecond.get(elem));
		}
		in.close();
		BufferedReader br = this.getBufferedReader();
		while ((str = br.readLine()) != null) {
			token = new StringTokenizer(str);
			while (token.hasMoreTokens()) {
				str = token.nextToken();
				if (str.equals("8")) {
					str = token.nextToken();
					if (str.contains("0")) {
						str = token.nextToken();
						String elem = str;

						for (i = 0; i <= 8; i++) {
							str = token.nextToken();
						}
						currentDiskQueueLength.put(elem,
								(double) Integer.parseInt(str));
					}
				}
			}
		}
		br.close();
		itr = instance.iterator();
		PhysicalDiskModel physicalDiskModel = new PhysicalDiskModel();
		while (itr.hasNext()) {
			String elem = itr.next();
			PhysicalDiskModelChild physicalDiskModelChild = new PhysicalDiskModelChild();
			physicalDiskModelChild.setInstance(elem);
			physicalDiskModelChild
					.setAverageDiskQueueLength(averageDiskQueueLength.get(elem));
			physicalDiskModelChild
					.setCurrentDiskQueueLength(currentDiskQueueLength.get(elem));
			physicalDiskModelChild.setDiskBytesPerSecond(diskBytesPerSecond
					.get(elem));
			physicalDiskModelChild
					.setDiskReadBytesPerSecond(diskReadBytesPerSecond.get(elem));
			physicalDiskModelChild
					.setDiskTimePercent(diskTimePercent.get(elem));
			physicalDiskModelChild
					.setDiskWriteBytesPerSecond(diskWriteBytesPerSecond
							.get(elem));
			physicalDiskModel.getPhysicalDiskModelList().add(
					physicalDiskModelChild);
		}
		return physicalDiskModel;
	}

}
