/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.oodt.cas.resource.monitor.ganglia;

//OODT imports
import org.apache.oodt.cas.resource.monitor.Monitor;
import org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculator;
import org.apache.oodt.cas.resource.structs.ResourceNode;
import org.apache.oodt.cas.resource.structs.exceptions.MonitorException;
import static org.apache.oodt.cas.resource.monitor.ganglia.GangliaMetKeys.NAME;

//JDK imports
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author rajith
 * @author mattmann
 * @version $Revision$
 */
public class GangliaResourceMonitor implements Monitor {

	private static final Logger LOG = Logger
			.getLogger(GangliaResourceMonitor.class.getName());
	private LoadCalculator loadCalculator;
	private Map<String, Integer> loadMap;
	private Map<String, Map<String, String>> gmetaNodes;
	private Map<String, GangliaAdapter> gmetaAdapters;
	private static final int DEFAULT_PORT = 8649;

	/**
	 * Make a new GangliaResourceMonitor that reads information from a ganglia
	 * meta daemon.
	 * 
	 * @param loadCalculator
	 *            LoadCalculator
	 *            {@link org.apache.oodt.cas.resource.monitor.ganglia.loadcalc.LoadCalculator}
	 *            to calculate load
	 * @param nodes
	 *            resource nodes
	 *            {@link org.apache.oodt.cas.resource.structs.ResourceNode} to
	 *            be monitored.
	 */
	public GangliaResourceMonitor(LoadCalculator loadCalculator,
			String gmetadHost, int gmetadPort) {
		this.loadCalculator = loadCalculator;
		this.loadMap = new HashMap<String, Integer>();
		this.gmetaNodes = new HashMap<String, Map<String, String>>();
		this.gmetaAdapters = new HashMap<String, GangliaAdapter>();
		try {
			this.initGmetaNodes(gmetadHost, gmetadPort);
		} catch (Exception e) {
			e.printStackTrace();
			LOG.log(Level.WARNING,
					"URL exception initializing gmetad nodes: [" + gmetadHost
							+ ":" + gmetadPort + "]: Message: "
							+ e.getMessage());
		}

	}

	@Override
	public int getLoad(ResourceNode node) throws MonitorException {
		Map<String, String> nodeProperties = null;
		String nodeId = node.getNodeId();
		nodeProperties = this.locateNode(nodeId);
		if (nodeProperties == null) {
			throw new MonitorException(
					"GangliaMonitor: not tracking requested node: [" + nodeId
							+ "]");
		}

		// calculate load
		double calcLoad = this.loadCalculator.calculateLoad(nodeProperties);
		System.out.println(calcLoad);
		int load = new Long(Math.round(calcLoad)).intValue();
		System.out.println("LOAD is: "+load);
		return load;
	}

	@Override
	public boolean assignLoad(ResourceNode node, int loadValue)
			throws MonitorException {
		// technically this method should simply do nothing, since
		// putting a job onto a node should cause Ganglia to detect
		// for now we'll simply track what the current perceived load
		// on a node is - we may want to factor this into the weighting
		// in load calculator later
		String nodeId = node.getNodeId();
		if (loadMap.containsKey(nodeId)) {
			int currLoad = loadMap.get(nodeId);
			currLoad += loadValue;
			loadMap.put(nodeId, currLoad);
		} else {
			loadMap.put(nodeId, loadValue);
		}
		return true;
	}

	@Override
	public void addNode(ResourceNode node) {
		this.addGmetadNode(node.getIpAddr().getHost(), node.getIpAddr()
				.getPort());
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void removeNodeById(String nodeId) {
		this.removeGmetadNode(nodeId);
	}

	@Override
	public List getNodes() throws MonitorException {
		List<ResourceNode> nodes = new Vector<ResourceNode>();
		if (this.gmetaAdapters != null) {
			for (GangliaAdapter adapter : this.gmetaAdapters.values()) {
				Map<String, Map<String, String>> aNodes = adapter
						.getResourceNodeStatus();
				for (Map<String, String> map : aNodes.values()) {
					try {
						nodes.add(this.nodeFromMap(map));
					} catch (MalformedURLException e) {
						e.printStackTrace();
						throw new MonitorException(e.getMessage());
					}
				}
			}
		}

		return nodes;
	}

	@Override
	public ResourceNode getNodeById(String nodeId) throws MonitorException {
		try {
			return this.nodeFromMap(this.locateNode(nodeId));
		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new MonitorException(e.getMessage());
		}
	}

	@Override
	public ResourceNode getNodeByURL(URL ipAddr) throws MonitorException {
		if (this.gmetaAdapters != null) {
			for (GangliaAdapter adapter : this.gmetaAdapters.values()) {
				Map<String, Map<String, String>> aNodes = adapter
						.getResourceNodeStatus();
				for (String aNodeId : aNodes.keySet()) {
					String host = ipAddr.getHost();
					int port = ipAddr.getPort();
					Map<String, String> nodeProps = aNodes.get(aNodeId);
					if (aNodeId.equals(host)
							&& nodeProps.get(DEFAULT_PORT).equals(
									String.valueOf(port))) {
						try {
							return this.nodeFromMap(aNodes.get(aNodeId));
						} catch (MalformedURLException e) {
							e.printStackTrace();
							throw new MonitorException(e.getMessage());
						}
					}
				}
			}
		}

		return null;
	}

	@Override
	public boolean reduceLoad(ResourceNode node, int loadValue)
			throws MonitorException {
		String nodeId = node.getNodeId();
		if (this.loadMap.containsKey(nodeId)) {
			int currLoad = loadMap.get(nodeId);
			currLoad = Math.min(0, currLoad - loadValue);
			this.loadMap.put(nodeId, currLoad);
		} else {
			this.loadMap.put(nodeId, 0);
		}
		
		return true;
	}

	private Map<String, String> locateNode(String nodeId) {
		if (this.gmetaAdapters != null && this.gmetaAdapters.size() > 0) {
			for (String nId : this.gmetaAdapters.keySet()) {
				GangliaAdapter adapter = this.gmetaAdapters.get(nId);
				try {
					System.out.println("Querying gmetad: ["+adapter.getUrlString()+"]");
					Map<String, Map<String, String>> nodeStatus = adapter
							.getResourceNodeStatus();
					System.out.println("Looking for nodeid: ["+nodeId+"]");
					if (nodeStatus.containsKey(nodeId)) {
						System.out.println("NODE met: "+nodeStatus.get(nodeId));
						return nodeStatus.get(nodeId);
					}
				} catch (MonitorException e) {
					LOG.log(Level.WARNING,
							"MonitorException contacting Ganglia: ["
									+ adapter.getUrlString() + "]");
					e.printStackTrace();
				}
			}

		}

		return null;
	}

	private ResourceNode nodeFromMap(Map<String, String> map)
			throws MalformedURLException {
		if (map == null) return null;
		ResourceNode node = new ResourceNode();
		System.out.println("MAP IS "+map);
		System.out.println("Setting hostname to "+map.get(NAME));
		node.setId(map.get(NAME));
		node.setIpAddr(new URL("http://" + map.get(NAME) + ":" + DEFAULT_PORT));
		return node;
	}

	private void initGmetaNodes(String host, int port)
			throws MalformedURLException {
		this.addGmetadNode(host, port);
	}

	private GangliaAdapter createAdapter(Map<String, String> node) {
		return new GangliaAdapter(node.get("host"), Integer.valueOf(node
				.get("port")));
	}

	private void addGmetadNode(String host, int port) {
		Map<String, String> rootNode = new HashMap<String, String>();
		rootNode.put("host", host);
		rootNode.put("port", String.valueOf(port));
		this.gmetaNodes.put(host, rootNode);
		this.gmetaAdapters.put(host, this.createAdapter(rootNode));
	}

	private void removeGmetadNode(String host) {
		if (this.gmetaNodes.containsKey(host)
				&& this.gmetaAdapters.containsKey(host)) {
			LOG.log(Level.FINE,
					"Removing gmetad node: ["
							+ gmetaAdapters.get(host).getUrlString() + "]");
			this.gmetaAdapters.remove(host);
			this.gmetaNodes.remove(host);
		}
	}

}
