/*******************************************************************************
 * 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.stericFilter;

import java.io.IOException;
import java.util.ArrayList;

import edu.duke.donaldLab.jdshot.grid.GridPoint;
import edu.duke.donaldLab.jdshot.grid.StructureGenerator;
import edu.duke.donaldLab.jdshot.search.SearchContext;
import edu.duke.donaldLab.share.bond.AtomAddressPair;
import edu.duke.donaldLab.share.bond.BondGraph;
import edu.duke.donaldLab.share.bond.BondGraphBuilder;
import edu.duke.donaldLab.share.protein.Protein;
import edu.duke.donaldLab.share.steric.StericChecker;

public class StericFilterProcessor implements Runnable
{
	/**************************
	 *   Data Members
	 **************************/
	
	private StericFilterSynchronizer m_synch;
	private SearchContext m_searchContext;
	private double m_epsilon;
	
	
	/**************************
	 *   Constructors
	 **************************/
	
	public StericFilterProcessor( StericFilterSynchronizer synch, SearchContext searchContext, double epsilon )
	{
		m_synch = synch;
		m_searchContext = searchContext;
		m_epsilon = epsilon;
	}
	
	
	/**************************
	 *   Methods
	 **************************/
	
	public void run( )
	{
		String name = Thread.currentThread().getName();
		System.out.println( name + ": Processor started!" );
		
		try
		{
			// get some objects we'll need
			// use sparse monomers since we only care about backbone atoms
			StericChecker stericChecker = new StericChecker();
			StructureGenerator generator = m_searchContext.getSymmetry().newStructureGenerator( m_searchContext.getMonomer().getBackbone() );
			
			/* Jeff: 12/03/2008 - NOTE:
				Since all of our structures will have the same connectivity and we're using
				atom addresses instead of java object references, we can cache one set of
				bond graphs for all our computed structures.
			*/
			ArrayList<BondGraph> bondGraphs = null;
			ArrayList<AtomAddressPair> stericPairs = null;
			
			ArrayList<GridPoint> points = null;
			while( true )
			{
				// ask the synch for a batch of points
				points = m_synch.getPoints();
				if( points == null || points.size() == 0 )
				{
					break;
				}
				
				for( GridPoint point : points )
				{
					// generate the protein structure and get the bond graphs if needed
					Protein structure = generator.getStructure( point, m_searchContext.getNumSubunits() );
					if( bondGraphs == null )
					{
						bondGraphs = BondGraphBuilder.getInstance().build( structure );
						stericPairs = stericChecker.getStericPairs( structure, bondGraphs );
					}
					
					// check the point's structure for steric clashes
					//if( stericChecker.proteinHasBackboneClash( structure, bondGraphs, m_epsilon ) )
					if( stericChecker.proteinHasBackboneClashFromPairs( structure, stericPairs, m_epsilon ) )
					{
						m_synch.rejectPoint( point );
					}
					else
					{
						m_synch.acceptPoint( point );
					}
				}
			}
		}
		catch( IOException ex )
		{
			System.err.println( name + ": Processor unable to process point! Halting Processor!" );
			ex.printStackTrace( System.err );
		}
		
		System.out.println( name + ": Processor finished!" );
	}
}
