/* Copyright (c) 2012,
 * Mathias Kuhring, KuhringM@rki.de, Robert Koch-Institut, Germany, 
 * All rights reserved. For details, please note the license.txt.
 */

package de.rki.ng4.ipig.mapping;

import java.util.Comparator;
import java.util.Vector;

/**
 * <p>A Position object is used to keep the informations of a peptide-genome mapping, including e.g. the gene name,
 * the chromosome, the strand and start and end positions (several if peptide is located in different exons).</p>
 * 
 * @author Mathias Kuhring
 */
public class Position {
	// variables to be set by a match
	private String geneName;
	private String chrom;
	private char strand;
	private Vector<Integer> startPos;
	private Vector<Integer> endPos;

	private boolean validated;
	private String modifier;

	/**
	 * Simple initialization.
	 */
	public Position(){
		startPos = new Vector<Integer>();
		endPos = new Vector<Integer>();
	}

	/**
	 * Set the name of the gene where this Position is located.
	 * 
	 * @param name a gene name as String
	 */
	public void setGeneName(String name){
		geneName = name;
	}

	/**
	 * Returns the name of the gene where this Position is located.
	 * 
	 * @return the gene name
	 */
	public String getGeneName(){
		return geneName;
	}

	/**
	 * Set the chromosome of this Position (e.g. "chr12", "chrVI").
	 * 
	 * @param chr
	 */
	public void setChrom(String chr){
		chrom = chr;
	}

	/**
	 * Returns the chromosome where this Position is located.
	 * 
	 * @return a chromosome name
	 */
	public String getChrom(){
		return chrom;
	}

	/**
	 * Set the strand of this Position.
	 * 
	 * @param str the strand as char, either '+' or '-'
	 */
	public void setStrand(char str) {
		strand = str;
	}

	/**
	 * Returns the strand of this Position.
	 * '+' for the positive strand and '-' for the negative one.
	 * 
	 * @return str the strand as char, either '+' or '-'
	 */
	public char getStrand(){
		return strand;
	}

	/**
	 * Adds a start position (on a chromosome) to a vector of start positions.
	 * @param pos The first or a further start position
	 */
	public void addStartPos(int pos){
		startPos.add(pos);
	}

	/**
	 * <p> Returns a Vector with all start positions. More than one start positions indicates a peptide over more than one exon.</p>
	 * <p> Use together with {@link #getEndPos()}, {@link #getChrom()} and {@link #getStrand()} for a complete localization.</p>
	 * 
	 * @return Vector of start positions
	 */
	public Vector<Integer> getStartPos(){
		return startPos;
	}

	/**
	 * Adds a end position (on a chromosome) to a vector of end positions.
	 * @param pos The first or a further end position
	 */
	public void addEndPos(int pos) {
		endPos.add(pos);
	}

	/**
	 * <p> Returns a Vector with all end positions. More than one end positions indicates a peptide over more than one exon.</p>
	 * <p> Use together with {@link #getStartPos()}, {@link #getChrom()} and {@link #getStrand()} for a complete localization.</p>
	 * 
	 * @return Vector of start positions
	 */
	public Vector<Integer> getEndPos(){
		return endPos;
	}

	/**
	 * Set a boolean value, if this Position has been validated.
	 * 
	 * @param validated set true if validated, false else
	 */
	public void setValidated(boolean validated) {
		this.validated = validated;
	}
	
	/**
	 * Returns if this Position has been validated (as set by {@link #setValidated(boolean)}).
	 * 
	 * @return true if validated, false else
	 */
	public boolean isValidated() {
		return validated;
	}
	
	/**
	 * Set a modifier which can be used to e.g. differentiate Positions.
	 * 
	 * @param modifier arbitrary String
	 */
	public void setModifier(String modifier) {
		this.modifier = modifier;
	}
	
	/**
	 * Returns the modifier.
	 * 
	 * @return modifier String if set, "" if null
	 */
	public String getModifier() {
		if (modifier == null)
			return "";
		return modifier;
	}

	/**
	 * A Comparator to sort Positions by the chromosome, strand, start position and end position.
	 * 
	 * @author Mathias Kuhring
	 */
	static public class PositionComparator implements Comparator<Position> {
		@Override
		public int compare(Position pos0, Position pos1) {
			int result;
			if ((result = pos0.getChrom().compareTo(pos1.getChrom())) == 0){
				if ((result = ((Character) pos0.getStrand()).compareTo((Character) pos1.getStrand())) == 0){
					if (!pos0.getStartPos().equals(pos1.getStartPos()) ||
							!pos0.getEndPos().equals(pos1.getEndPos())){
						int min = Math.min(pos0.getStartPos().size(), pos1.getStartPos().size());
						result = -1;
						for (int i=0; i<min; i++){
							if (pos0.getStartPos().get(i) > pos1.getStartPos().get(i)){
								result = 1;
								break;
							}
						}
						for (int i=0; i<min; i++){
							if (pos0.getEndPos().get(i) > pos1.getEndPos().get(i)){
								result = 1;
								break;
							}
						}
					}
				}
			}
			return result;
		}
	}
}
