package org.pmdreports.model;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

/**
 * ComponentStatisticsVO.java<br>
 * 
 * Stores all attributes relevant to a component for this application.
 * 
 * @author Ben Northrop
 */
public class Statistics {

	// DATA MEMBERS
	private final static Logger LOG = Logger.getLogger(Statistics.class);

	private Component component;

	private long linesOfCode;

	private long linesOfComments;

	private long numberOfFiles;

	private Date dateCalculated;

	private final Map<Ruleset, Double> statisticsMap = new HashMap<Ruleset, Double>();

	// CONSTRUCTOR
	/**
	 * @param componentName
	 */
	public Statistics(Component component) {
		setComponent(component);
	}

	/**
	 * Add a statistic given it's name and value.
	 */
	public void addStatistic(Ruleset ruleset, Double value) {
		statisticsMap.put(ruleset, value);
	}

	/**
	 * Add a statistic given it's name and value.
	 */
	public void addStatistic(Ruleset ruleset, Integer value) {
		statisticsMap.put(ruleset, new Double(value));
	}

	/**
	 * Get the total number of violations for this statistics line.
	 */
	public Double getTotalViolations(boolean isPerLine) {
		Set<Ruleset> rulesets = statisticsMap.keySet();
		double total = 0d;
		for (Ruleset ruleset : rulesets) {
			total += getStatistic(ruleset, isPerLine);
		}
		return total;
	}

	/**
	 * Get the statistic using the isAbsolute value.
	 */
	public Double getStatistic(Ruleset ruleset) {
		return getStatistic(ruleset, !ruleset.getIsShowAbsolute());
	}
	

	/**
	 * Get the statistic given its name.
	 */
	public Double getStatistic(Ruleset ruleset, boolean isPerLine) {
		Double stat = (Double) statisticsMap.get(ruleset);
		if (stat == null) {
			LOG.debug("No statistic for rule: " + ruleset.getName()
					+ " component: " + getComponent().getName());
			return 0.0d;
		}
		return isPerLine ? (stat / linesOfCode) * 1000 : stat;
	}

	/**
	 * Get the name of all the statisticsMap.
	 */
	public Set<Ruleset> getRulesets() {
		return statisticsMap.keySet();
	}

	// METHODS
	/**
	 * Generate a String representation of all statisticsMap.
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append(component.getName());
		Set<Ruleset> statKeys = statisticsMap.keySet();
		for (Ruleset key : statKeys) {
			sb.append("\n  ");
			sb.append(key);
			sb.append(": ");
			sb.append(getStatistic(key, true));
			sb.append(", ");
			sb.append(getStatistic(key, false));
		}
		return sb.toString();
	}

	/**
	 * @return the linesOfCode
	 */
	public long getLinesOfCode() {
		return linesOfCode;
	}

	/**
	 * @param linesOfCode
	 *            the linesOfCode to set
	 */
	public void setLinesOfCode(long linesOfCode) {
		this.linesOfCode = linesOfCode;
	}

	/**
	 * @return the linesOfComments
	 */
	public long getLinesOfComments() {
		return linesOfComments;
	}

	/**
	 * @param linesOfComments
	 *            the linesOfComments to set
	 */
	public void setLinesOfComments(long linesOfComments) {
		this.linesOfComments = linesOfComments;
	}

	/**
	 * @return the componentName
	 */
	public Component getComponent() {
		return component;
	}

	/**
	 * @return the dateCalculated
	 */
	public Date getDateCalculated() {
		return dateCalculated;
	}

	/**
	 * @param dateCalculated
	 *            the dateCalculated to set
	 */
	public void setDateCalculated(Date dateCalculated) {
		this.dateCalculated = dateCalculated;
	}

	/**
	 * @param component
	 *            the component to set
	 */
	public final void setComponent(Component component) {
		this.component = component;
	}

	/**
	 * @return the numberOfFiles
	 */
	public long getNumberOfFiles() {
		return numberOfFiles;
	}

	/**
	 * @param numberOfFiles
	 *            the numberOfFiles to set
	 */
	public void setNumberOfJavaFiles(long numberOfFiles) {
		this.numberOfFiles = numberOfFiles;
	}

}
