package cn.edu.seu.ise.dca.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Revision {
	private long id;
	private String author;
	private Date commitDate;
	private List<ChangedFile> changedFiles;

	public Revision(long id, String author, Date commitDate) {
		this.id = id;
		this.author = author;
		this.commitDate = commitDate;
		this.changedFiles = new ArrayList<ChangedFile>();
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public Date getCommitDate() {
		return commitDate;
	}

	public void setCommitDate(Date commitDate) {
		this.commitDate = commitDate;
	}
	
	public List<ChangedFile> getChangedFiles() {
		return changedFiles;
	}

	public void setChangedFiles(List<ChangedFile> changedFiles) {
		this.changedFiles = changedFiles;
	}
	
	public void addChangedFile(ChangedFile changedFile) {
		changedFiles.add(changedFile);
	}
	
	/**
	 * Return the number of all changed files in this revision
	 * @return the number of changed paths
	 */
	public int sizeOfChangedFiles() {
		return changedFiles.size();
	}
		
	/**
	 * Return the number of all changed files in this revision
	 * @return the number of changed paths
	 */
	public int sizeOfAddedFiles() {
		int files = 0;
		for(ChangedFile changedFile : changedFiles) {
			if(changedFile.getChangeType() == 'A')
				files ++;
		}
		return files;
	}
		
	/**
	 * Return the number of all deleted files in this revision
	 * @return the number of changed paths
	 */
	public int sizeOfDeletedFiles() {
		int files = 0;
		for(ChangedFile changedFile : changedFiles) {
			if(changedFile.getChangeType() == 'D')
				files ++;
		}
		return files;
	}
	
	/**
	 * Return the number of all deleted files in this revision
	 * @return the number of changed paths
	 */
	public int sizeOfModifiedFiles() {
		int files = 0;
		for(ChangedFile changedFile : changedFiles) {
			if(changedFile.getChangeType() == 'M')
				files ++;
		}
		return files;
	}
	
	/**
	 * Return the number of total code lines with in current revision  
	 * @param isRevised
	 * @return
	 */
	public long sizeOfLines(boolean isRevised) {
		long lines = 0;
		for(ChangedFile file : changedFiles) {
			lines += file.sizeOfLines(isRevised);
		}
		return lines;
	}
	
	/**
	 * Return the number of total code lines with in current revision (without comment and blank lines)
	 * @param isRevised
	 * @return
	 */
	public long sizeOfActLines(boolean isRevised) {
		long lines = 0;
		for(ChangedFile file : changedFiles) {
			lines += file.sizeOfActLines(isRevised);
		}
		return lines;
	}
	
	/**
	 * Return the number of total changed code lines with in 
	 * current revision  
	 * @param isRevised
	 * @return
	 */
	public long sizeOfChangedLines(boolean isRevised, boolean hasComments) {
		long lines = 0;
		for(ChangedFile file : changedFiles) {
			lines += file.sizeOfChangedLines(isRevised, hasComments);
		}
		return lines;
	}
	
	/**
	 * Return the number of total added code lines with in current revision  
	 * @return
	 */
	public long sizeOfAddedLines(boolean hasComments) {
		long lines = 0;
		for(ChangedFile file : changedFiles) {
			lines += file.sizeOfAddedLines(hasComments);
		}
		return lines;
	}
	
	/**
	 * Return the number of total deleted code lines with in current revision  
	 * @return
	 */
	public long sizeOfDeletedLines(boolean hasComments) {
		long lines = 0;
		for(ChangedFile file : changedFiles) {
			lines += file.sizeOfDeletedLines(hasComments);
		}
		return lines;
	}
	
	/**
	 * Return the number of total modified code lines with in 
	 * current revision  
	 * @param isRevised
	 * @return
	 */
	public long sizeOfModifiedLines(boolean isRevised, boolean hasComments) {
		long lines = 0;
		for(ChangedFile file : changedFiles) {
			lines += file.sizeOfModifiedLines(isRevised, hasComments);
		}
		return lines;
	}
	
	/**
	 * Return the number of total classes in current revision  
	 * @return
	 */
	public long sizeOfClasses() {
		long classes = 0;
		for(ChangedFile file : changedFiles) {
			classes += file.sizeOfClasses(true);
		}
		return classes;
	}
	
	/**
	 * Return the number of total changed classes in current revision  
	 * @return
	 */
	public long sizeOfChangedClasses() {
		long classes = 0;
		for(ChangedFile file : changedFiles) {
			classes += file.sizeOfChangedClasses();
		}
		return classes;
	}
	
	/**
	 * Return the number of added classes in current revision  
	 * @return
	 */
	public long sizeOfAddedClasses() {
		long classes = 0;
		for(ChangedFile file : changedFiles) {
			classes += file.sizeOfAddedClasses();
		}
		return classes;
	}
	
	/**
	 * Return the number of deleted classes with in current revision  
	 * @return
	 */
	public long sizeOfDeletedClasses() {
		long classes = 0;
		for(ChangedFile file : changedFiles) {
			classes += file.sizeOfDeletedClasses();
		}
		return classes;
	}
	
	/**
	 * Return the number of modified classes with in current revision  
	 * @return
	 */
	public long sizeOfModifiedClasses() {
		long classes = 0;
		for(ChangedFile file : changedFiles) {
			classes += file.sizeOfModifiedClasses();
		}
		return classes;
	}
	
	/**
	 * Return the number of total changed global functions with in current revision  
	 * @return
	 */
	public long sizeOfGlobalFunctions() {
		long globals = 0;
		for(ChangedFile file : changedFiles) {
			globals += file.sizeOfGlobalFunctions(true);
		}
		return globals;
	}
	
	/**
	 * Return the number of total changed global functions with in current revision  
	 * @return
	 */
	public long sizeOfChangedGlobalFunctions() {
		long globals = 0;
		for(ChangedFile file : changedFiles) {
			globals += file.sizeOfChangedGlobalFunctions();
		}
		return globals;
	}
	
	/**
	 * Return the number of added global functions with in current revision  
	 * @return
	 */
	public long sizeOfAddedGlobalFunctions() {
		long globals = 0;
		for(ChangedFile file : changedFiles) {
			globals += file.sizeOfAddedGlobalFunctions();
		}
		return globals;
	}
	
	/**
	 * Return the number of deleted global functions with in current revision  
	 * @return
	 */
	public long sizeOfDeletedGlobalFunctions() {
		long globals = 0;
		for(ChangedFile file : changedFiles) {
			globals += file.sizeOfDeletedGlobalFunctions();
		}
		return globals;
	}
	
	/**
	 * Return the number of modified global functions with in current revision  
	 * @return
	 */
	public long sizeOfModifiedGlobalFunctions() {
		long globals = 0;
		for(ChangedFile file : changedFiles) {
			globals += file.sizeOfModifiedGlobalFunctions();
		}
		return globals;
	}
	
	/**
	 * Return the number of total member functions with in current revision  
	 * @return
	 */
	public long sizeOfMemberFunctions() {
		long members = 0;
		for(ChangedFile file : changedFiles) {
			members += file.sizeOfMemberFunctions(true);
		}
		return members;
	}
	
	/**
	 * Return the number of total changed member functions with in current revision  
	 * @return
	 */
	public long sizeOfChangedMemberFunctions() {
		long members = 0;
		for(ChangedFile file : changedFiles) {
			members += file.sizeOfChangedMemberFunctions();
		}
		return members;
	}
	
	/**
	 * Return the number of added member functions with in current revision  
	 * @return
	 */
	public long sizeOfAddedMemberFunctions() {
		long members = 0;
		for(ChangedFile file : changedFiles) {
			members += file.sizeOfAddedMemberFunctions();
		}
		return members;
	}
	
	/**
	 * Return the number of deleted member functions with in current revision  
	 * @return
	 */
	public long sizeOfDeletedMemberFunctions() {
		long members = 0;
		for(ChangedFile file : changedFiles) {
			members += file.sizeOfDeletedMemberFunctions();
		}
		return members;
	}
	
	/**
	 * Return the number of modified member functions with in current revision  
	 * @return
	 */
	public long sizeOfModifiedMemberFunctions() {
		long members = 0;
		for(ChangedFile file : changedFiles) {
			members += file.sizeOfModifiedMemberFunctions();
		}
		return members;
	}
	
	/**
	 * Return the report of the changed files in the current revision
	 * @return
	 */
	public String reportChangedFiles() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("Files [Total-").append(this.sizeOfChangedFiles())
			.append(" Added-").append(this.sizeOfAddedFiles())
			.append(" Deleted-").append(this.sizeOfDeletedFiles())
			.append(" Modified-").append(this.sizeOfModifiedFiles())
			.append("]");
		return buffer.toString();
	}
	
	/**
	 * Return the report of the changed lines in the current revision
	 * @return
	 */
	public String reportChangedLines(boolean hasComments) {
		StringBuffer buffer = new StringBuffer();
		if(!hasComments) {
			buffer.append("LOCs [Total(O)-").append(this.sizeOfLines(false))
				.append(" Total(R)-").append(this.sizeOfLines(true));
		} else {
			buffer.append("LOCs [Total(O)-").append(this.sizeOfActLines(false))
				.append(" Total(R)-").append(this.sizeOfActLines(true));
		}
		buffer.append(" Added-").append(this.sizeOfAddedLines(hasComments))
			.append(" Deleted-").append(this.sizeOfDeletedLines(hasComments))
			.append(" Modified(O)-").append(this.sizeOfModifiedLines(false, hasComments))
			.append(" Modified(R)-").append(this.sizeOfModifiedLines(true, hasComments))
			.append(" TChanged(O)-").append(this.sizeOfChangedLines(false, hasComments))
			.append(" TChanged(R)-").append(this.sizeOfChangedLines(true, hasComments))
			.append("]");
		return buffer.toString();
	}
	
	/**
	 * Return the report of the changed classes in the current revision
	 * @return
	 */
	public String reportChangedClasses() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("Class [Total-").append(this.sizeOfClasses())
			.append(" Added-").append(this.sizeOfAddedClasses())
			.append(" Deleted-").append(this.sizeOfDeletedClasses())
			.append(" Modified-").append(this.sizeOfModifiedClasses())
			.append(" TotalChanged-").append(this.sizeOfChangedClasses())
			.append("]");
		return buffer.toString();
	}
	
	/**
	 * Return the report of the changed global function in the current revision
	 * @return
	 */
	public String reportChangedGlobalFunctions() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("GFunc [Total-").append(this.sizeOfGlobalFunctions())
			.append(" Added-").append(this.sizeOfAddedGlobalFunctions())
			.append(" Deleted-").append(this.sizeOfDeletedGlobalFunctions())
			.append(" Modified-").append(this.sizeOfModifiedGlobalFunctions())
			.append(" TotalChanged-").append(this.sizeOfChangedGlobalFunctions())
			.append("]");
		return buffer.toString();
	}
	
	/**
	 * Return the report of the changed member function in the current revision
	 * @return
	 */
	public String reportChangedMemberFunctions() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("MFunc [Total-").append(this.sizeOfMemberFunctions())
			.append(" Added-").append(this.sizeOfAddedMemberFunctions())
			.append(" Deleted-").append(this.sizeOfDeletedMemberFunctions())
			.append(" Modified-").append(this.sizeOfModifiedMemberFunctions())
			.append(" TotalChanged-").append(this.sizeOfChangedMemberFunctions())
			.append("]");
		return buffer.toString();
	}
	
	@Override
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("Revision: ").append(this.id).append("\t")
			.append("Author: ").append(this.author).append("\t")
			.append("Date: ").append(this.commitDate);
		return buffer.toString();
	}
	
}
