/*******************************************************************************
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 * 
 * Contact Info:
 * 	Bruce Donald
 * 	Duke University
 * 	Department of Computer Science
 * 	Levine Science Research Center (LSRC)
 * 	Durham
 * 	NC 27708-0129 
 * 	USA
 * 	brd@cs.duke.edu
 * 
 * Copyright (C) 2011 Jeffrey W. Martin and Bruce R. Donald
 * 
 * <signature of Bruce Donald>, April 2011
 * Bruce Donald, Professor of Computer Science
 ******************************************************************************/


package edu.duke.donaldLab.jdshot.disco;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

import edu.duke.donaldLab.share.pdb.ProteinWriter;
import edu.duke.donaldLab.share.protein.Protein;


@SuppressWarnings("serial")
public class StructureScores implements Iterable<StructureScores.Score>, Serializable
{
	/**************************
	 *   Definitions
	 **************************/
	
	private static final Logger m_log = Logger.getLogger( StructureScores.class );
	
	public static class ScoreSample implements Serializable
	{
		public double energy;
		public double restraintRmsd;
		public int numRestraintsSatisfied;
		
		public ScoreSample( double energy, double restraintRmsd, int numRestraintsSatisfied )
		{
			this.energy = energy;
			this.restraintRmsd = restraintRmsd;
			this.numRestraintsSatisfied = numRestraintsSatisfied;
		}
	}
	
	public static class Score implements Serializable
	{
		public ScoreSample before;
		public ScoreSample after;
		public transient Protein minimizedStructure;
		
		public Score( ScoreSample before, ScoreSample after, Protein minimizedStructure )
		{
			this.before = before;
			this.after = after;
			this.minimizedStructure = minimizedStructure;
		}
	}
	
	
	/**************************
	 *   Data Members
	 **************************/
	
	private ArrayList<Score> m_scores;
	
	
	/**************************
	 *   Constructors
	 **************************/
	
	public StructureScores( int numScores )
	{
		m_scores = new ArrayList<Score>( numScores );
		for( int i=0; i<numScores; i++ )
		{
			m_scores.add( null );
		}
	}
	
	
	/**************************
	 *   Methods
	 **************************/
	
	public void set( int index, Score score )
	{
		m_scores.set( index, score );
	}
	
	public int getNumScores( )
	{
		return m_scores.size();
	}
	
	@Override
	public Iterator<Score> iterator( )
	{
		return m_scores.iterator();
	}
	
	public List<ScoreSample> getBeforeSamples( )
	{
		ArrayList<ScoreSample> samples = new ArrayList<ScoreSample>( m_scores.size() );
		for( Score score : m_scores )
		{
			samples.add( score.before );
		}
		return samples;
	}
	
	public List<ScoreSample> getAfterSamples( )
	{
		ArrayList<ScoreSample> samples = new ArrayList<ScoreSample>( m_scores.size() );
		for( Score score : m_scores )
		{
			samples.add( score.after );
		}
		return samples;
	}
	
	public void writeBeforeToFile( File outFile )
	throws IOException
	{
		writeScoreSamplesToFile( outFile, getBeforeSamples() );
	}
	
	public void writeAfterToFile( File outFile )
	throws IOException
	{
		writeScoreSamplesToFile( outFile, getAfterSamples() );
	}
	
	public void writeMinimizedStrcutures( File outFile )
	throws IOException
	{
		// collect the minimized structures
		ArrayList<Protein> minimizedStructures = new ArrayList<Protein>( m_scores.size() );
		for( Score score : m_scores )
		{
			minimizedStructures.add( score.minimizedStructure );
		}
		
		new ProteinWriter().write( minimizedStructures, outFile );
	}
	
	public boolean hasError( )
	{
		for( Score score : m_scores )
		{
			if( score == null )
			{
				return true;
			}
		}
		return false;
	}
	
	
	/**************************
	 *   Functions
	 **************************/
	
	private void writeScoreSamplesToFile( File outFile, List<ScoreSample> samples )
	throws IOException
	{
		FileWriter out = new FileWriter( outFile );
		out.write( String.format( "%s\t%s\t%s\n", "vdW Energy", "Distance Restraint RMSD", "Num Satisfied Distance Restraints" ) );
		for( ScoreSample sample : samples )
		{
			out.write( Double.toString( sample.energy ) );
			out.write( "\t" );
			out.write( Double.toString( sample.restraintRmsd ) );
			out.write( "\t" );
			out.write( Integer.toString( sample.numRestraintsSatisfied ) );
			out.write( "\n" );
		}
		m_log.info( "Wrote structure scores to:\n\t" + outFile.getAbsolutePath() );
		out.close();
	}
}
