/**
 * 
 * Written by Márton Münz and Philip C Biggin
 * Copyright (c) University of Oxford, United Kingdom
 * Visit http://sbcb.bioch.ox.ac.uk/jgromacs/
 * 
 * This source code file is part of JGromacs v1.0.
 * 
 * JGromacs v1.0 is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * JGromacs v1.0. is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with JGromacs v1.0. If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package jgromacs.data;

import java.util.ArrayList;

/**
 * Objects of this class represent a list of index sets
 *
 */
public class IndexSetList implements Cloneable{

	private ArrayList<IndexSet> indexsets = new ArrayList<IndexSet>();

	// Constructor

	/**
	 * Constructs a new IndexSetList object
	 *
	 * 
	 */
	public IndexSetList(){
		
	}
	
	// Getters
	
	/**
	 * Returns index set list as an ArrayList object
	 * @return index set list as an ArrayList
	 */
	public ArrayList<IndexSet> getAsAnArrayList(){
		return indexsets;
	}
	
	/**
	 * Returns the number of index sets in the list
	 * @return number of index sets
	 */
	public int getNumberOfIndexSets(){
		return indexsets.size();
	}
	
	/**
	 * Returns the index set of given index
	 * @param i index of index set
	 * @return index set of given index
	 */
	public IndexSet getIndexSet(int i){
		return (IndexSet)indexsets.get(i);	
	}
	
	/**
	 * Returns the index set of given name
	 * @param name name of index set
	 * @return index set of given name
	 */
	public IndexSet getIndexSet(String name){
		ArrayList<IndexSet> indexsets = getAsAnArrayList();
		for (int i = 0; i < indexsets.size(); i++) {
			IndexSet set = (IndexSet)indexsets.get(i);
			if (set.getName().equals(name)) return set;
		}
		return null;
	}
	
	/**
	 * Returns the number of atoms in the index set of given index
	 * @param i index of index set
	 * @return number of atoms
	 */
	public int getNumberOfAtomsInIndexSet(int i){
		 IndexSet set = getIndexSet(i);
		 return set.getNumberOfIndices();
	}
	
	/**
	 * Returns the number of atoms in the index set of given name
	 * @param name name of index set
	 * @return number of atoms
	 */
	public int getNumberOfAtomsInIndexSet(String name){
	 IndexSet set = getIndexSet(name);
	 return set.getNumberOfIndices();
	}
	
	// Modifications
	
	/**
	 * Adds a new index set to the list
	 * @param set new index set
	 */
	public void addIndexSet(IndexSet set){
		indexsets.add(set);
	}
	
	/**
	 * Adds a new index set of given name to the list
	 * @param set new index set
	 * @param name name of index set
	 */
	public void addIndexSet(IndexSet set, String name){
		set.setName(name);
		indexsets.add(set);
	}
	
	/**
	 * Removes index set of given index from the list
	 * @param i index of index set to be removed
	 */
	public void removeIndexSet(int i){
		indexsets.remove(i);
	}
	
	/**
	 * Removes the given index set from the list
	 * @param set index set to be removed
	 */
	public void removeIndexSet(IndexSet set){
		indexsets.remove(set);
	}
	
	/**
	 * Replaces index set of given index with a new index set
	 * @param i index of index set to be replaced
	 * @param set new index set
	 */
	public void setIndexSet(int i, IndexSet set){
		indexsets.set(i, set);
	}
	
	// Fusion of index sets

	/**
	 * Returns the union of all index sets as a single index set
	 * @return union of index sets
	 * 
	 */
	public IndexSet fuseIntoOneIndexSet(){
		IndexSet ret = new IndexSet();
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < indexsets.size(); i++) {
			IndexSet set = (IndexSet)indexsets.get(i);
			if (i>0) buf.append(",");
			buf.append(set.getName());
			ret = ret.union(set);
		}
		ret.setName("Fusion("+buf.toString()+")");
		return ret;
	}
	
	// toString, equals, clone
	
	/**
	 * Returns the String representation of index set list
	 *
	 * @return String representation
	 */
	public String toString(){
		StringBuffer buf = new StringBuffer();
		ArrayList<IndexSet> indexsets = getAsAnArrayList();
		for (int i = 0; i < indexsets.size(); i++) {
			IndexSet set = (IndexSet)indexsets.get(i);
			buf.append(set.toString()+"\n");	
		}
		return buf.toString();
	}
	
	/**
	 * Returns summary information about the index set list
	 *
	 * @return summary information
	 */
	public String toStringInfo(){
		return "("+getNumberOfIndexSets()+" index sets)";
	}
	
	/**
	 * Returns an identical IndexSetList object 
	 *
	 * @return clone of the index set list
	 */
	public Object clone(){
		try {
			IndexSetList ret = (IndexSetList)super.clone();
			ret.indexsets = new ArrayList<IndexSet>();
			for (int i = 0; i < indexsets.size(); i++)
			ret.addIndexSet(indexsets.get(i));
			return ret;
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
		
	}
	
	/**
	 * Returns true if the two index set lists are identical
	 * @param other the other index set list
	 * 
	 */
	public boolean equals(Object other){
		if (other == null) return false;
		if (other == this) return true;
		if (this.getClass() != other.getClass()) return false;
		IndexSetList setlist = (IndexSetList)other;
		if (setlist.getNumberOfIndexSets()!=getNumberOfIndexSets())
		return false;
		for (int i = 0; i < indexsets.size(); i++){
		if  (!getIndexSet(i).equals(setlist.getIndexSet(i))) return false;
		}
		return true;
	}
	
	/**
	 * Returns hash code
	 * 
	 */
	public int hashCode() {
		return indexsets.size();
	}
	
	
}
