package com.actelion.research.chem.sar;

import com.actelion.research.chem.StereoMolecule;

import java.util.ArrayList;

/**
 * A scaffold group comprises all scaffolds that arise from a match of the same query substructure in multiple
 * processed molecules. A scaffold group may contain more than one scaffold, if the substructure contains wild card
 * elements like atom lists, or multiple allowed bond orders. A special case are bridge bonds, which cause a query
 * match to contain more atoms than the query itself. Interestingly, these atoms may also carry R-groups, which needs
 * to be handled differently from the R-groups on the core atoms. Core atoms are those atoms for which an associated
 * atom exists in the query structure. R-groups (exit vectors) on core atom are numbered consistently within all
 * scaffolds that belong to the same scaffold group, i.e. that were detected from the same query structure.
 */
public class SARScaffoldGroup {
	private int mRGroupCount;
	private ExitVector[] mExitVector;
	private ArrayList<SARScaffold> mScaffoldList;

	protected SARScaffoldGroup(StereoMolecule query) {
		super();
		mRGroupCount = -1;
		analyzeExitVectors(query);
		mScaffoldList = new ArrayList<>();
	}

	public void addScaffold(SARScaffold scaffold) {
		mScaffoldList.add(scaffold);
	}

	public ArrayList<SARScaffold> getScaffoldList() {
		return mScaffoldList;
	}

	private void analyzeExitVectors(StereoMolecule query) {
		ArrayList<ExitVector> evList = new ArrayList<>();
		for (int atom=0; atom<query.getAtoms(); atom++) {
			if (!query.isExcludeGroupAtom(atom)) {
				int exitVectorCount = query.getLowestFreeValence(atom);
				for (int i=0; i<exitVectorCount; i++) {
					// If we have >= two exit vectors (with both one and two connAtoms in the query)
					// we assume that we can distinuish the exit vectors by topicity (any stereo criteria)
					int topicity = (exitVectorCount >= 2) ? i : -1;
					evList.add(new ExitVector(atom, true, i, topicity));
				}
			}
		}
		mExitVector = evList.toArray(new ExitVector[0]);
	}

	protected int getExitVectorCount() {
		return mExitVector.length;
	}

	/**
	 * Find correct exit vector index defining the core atom and for it either the exit vectors topicity
	 * (if exit vectors are stereo-heterotop) or just an index (if exit vectors are homotop)
	 * @param queryAtom respective atom index of query
	 * @param connIndex 0-based exo-query neighbour index (not used if topicity != -1 and neighbours are stereotop
	 * @param topicity -1, if exit vector neighbours are homotop, otherise 0 or 1
	 * @return index into list of all exit vectors of scaffold
	 */
	protected int getExitVectorIndex(int queryAtom, int connIndex, int topicity) {
		for (int i=0; i<mExitVector.length; i++)
			if (mExitVector[i].getQueryAtom() == queryAtom
			 && (((topicity == -1 || mExitVector[i].getTopicity() == -1) && mExitVector[i].getIndex() == connIndex)
			  || (topicity != -1 && mExitVector[i].getTopicity() == topicity)))
//{ System.out.println("getExitVectorIndex(queryAtom:"+queryAtom+", connIndex:"+connIndex+", topicity:"+topicity+") ev.index:"+mExitVector[i].getIndex()+" ev.topicity:"+mExitVector[i].getTopicity()+" evi:"+i);
				return i;
//}

//System.out.println("getExitVectorIndex(queryAtom:"+queryAtom+", connIndex:"+connIndex+", topicity:"+topicity+") evi:"+-1);
		return -1;
	}

	protected ExitVector getExitVector(int i) {
		return mExitVector[i];
	}

	protected int getRGroupCount() {
		return mRGroupCount;
	}

	protected int assignRGroups(int firstRGroup) {
		if (mRGroupCount == -1) {
			mRGroupCount = 0;
			for (int i=0; i<mExitVector.length; i++) {
				ExitVector exitVector = mExitVector[i];
				if (exitVector.substituentVaries()) {
					exitVector.setRGroupNo(++mRGroupCount + firstRGroup - 1);
//					if (!exitVector.hasSeenBondOrder(1)) {
//						i++;
//						if (!exitVector.hasSeenBondOrder(2))
//							i++;
//					}
				}
			}
		}
		return mRGroupCount;
	}
}
