package artificialFastqGenerator;

import java.util.ArrayList;

/**
 * An instance of this class corresponds to a read in an artificial fastq file. It has fields for its Nucleobase sequence,
 * unique integer ID, the other read in the pair, its encoded quality scores, and the genotypes which actually get read (i.e.
 * may contain error).
 * 
 * Copyright (C) 2012 The Institute of Cancer Research (ICR).
 *
 * This file is part of ArtificialFastqGenerator v1.0.0.
 * 
 * ArtificialFastqGenerator 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.
 * 
 * This program 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 Public License along with this
 * program. If not, see <http://www.gnu.org/licenses/>
 * 
 * Authour's contact email: Matthew.Frampton@icr.ac.uk
 */

public class Read extends AbstractRead {

	private long uniqueID;
	private Read pairedEndRead;
	private boolean leftPEAndNeedsWriting;
	private char[] encodedQualityScores;
	private char[] genotypesThatAreRead;
	private String machineLaneTileXYLorR = "HWI-ST745_0097:7:1101:";
	
	/**
	 * Initialise a new Read object.
	 * 
	 * @param sequence - the sequence of nucleobases in this read.
	 * @param uniqueID - the read's unique integer ID.
	 * @param pairedEndRead - the other read with which this one forms a pair.
	 * @param leftPEAndNeedsWriting - true if the read is a left read and needs writing, else false.
	 * @param encodedQualityScores - the encoded quality scores for this read.
	 * @param genotypesThatAreRead - the genotypes that get read.
	 * @param xCoordinate - the read's x-coordinate.
	 * @param yCoordinate - the read's y-coordinate.
	 */
	
	public Read(ArrayList<Nucleobase> sequence, long uniqueID, Read pairedEndRead, boolean leftPEAndNeedsWriting, char[] encodedQualityScores, 
			char[] genotypesThatAreRead, int xCoordinate, int yCoordinate) {
		this.sequence = sequence;
		this.uniqueID = uniqueID;
		this.pairedEndRead = pairedEndRead;
		updateNucleobaseCoverage(this);
		this.leftPEAndNeedsWriting = leftPEAndNeedsWriting;
		this.encodedQualityScores = encodedQualityScores;
		this.genotypesThatAreRead = genotypesThatAreRead;
		this.machineLaneTileXYLorR = this.machineLaneTileXYLorR + xCoordinate + ":" + yCoordinate + "#0/";
		if (leftPEAndNeedsWriting) {
			this.machineLaneTileXYLorR = this.machineLaneTileXYLorR + "1";
		} else {
			this.machineLaneTileXYLorR = this.machineLaneTileXYLorR + "2";
		}
	}
	
	/**
	 * Set whether the Read object is a left read and needs writing.
	 * 
	 * @param trueOrFalse - true if the read is a left read and needs writing, else false.
	 */
	
	public void setLeftReadAndNeedsWriting(boolean trueOrFalse) {
		leftPEAndNeedsWriting = trueOrFalse;
	}
	
	/**
	 * Get whether the Read object is a left read and needs writing.
	 * 
	 * @return leftPEAndNeedsWriting - whether the read is a left read and needs writing (hasn't been written yet), else false.
	 */
	
	public boolean isLeftReadAndNeedsWriting() {
		return leftPEAndNeedsWriting;
	}
	
	/**
	 * Get the read with which this read object forms a pair.
	 * 
	 * @return pairedEndRead - the read with which this read forms a pair.
	 */
	
	public Read getPairedEndRead() {
		return pairedEndRead;
	}
	
	/**
	 * Set the read with which this read object forms a pair.
	 * 
	 * @param pairedEndRead - the read with which this read forms a pair.
	 */
	
	public void setPairedEndRead(Read pairedEndRead) {
		this.pairedEndRead = pairedEndRead;
	}
	
	/**
	 * For each of the reference genome nucleobases in this read, add
	 * the read into the nucleobase's covering reads ArrayList.
	 * 
	 * @param read - this read.
	 */
	
	public void updateNucleobaseCoverage(Read read) {
		for (Nucleobase nucleobase : read.getSequence()) {
			if (!nucleobase.getCoveringReads().contains(read)) {
				nucleobase.addCoveringRead(read);}
			else {break;}
		}
	}
	
	/**
	 * Get the string that represents this read object. 
	 * 
	 * @return returnString - the string that represents this read object.
	 */
	
	public String toString() {
		
		String returnString = new String();
		
		if (Main.outputFormat.equals(Main.DEFAULT_OUTPUT)) {
			returnString = "@" + machineLaneTileXYLorR + "\n";
			for (int i=0; i<genotypesThatAreRead.length; i++) {
				returnString = returnString + genotypesThatAreRead[i];
			}
			returnString = returnString + "\n+" + machineLaneTileXYLorR + "\n";
			for (int i=0; i<encodedQualityScores.length; i++) {
				returnString = returnString + encodedQualityScores[i];
			}
			returnString = returnString + "\n";
		} else {
			returnString = getDebugString() + "\n";
		}
		
		return returnString;
	}
	
	/**
	 * Get the debug string for this read object.
	 * 
	 * @return returnString - the debug string that represents this read object.
	 */
	
	public String getDebugString() {
		
		String returnString = "";
		for (Nucleobase nucleobase : sequence) {
			returnString = returnString + nucleobase.toString();
		}
		if (Main.outputFormat.equals(Main.DEBUG_NUCLEOBASES_PE_IDS)) {
			String pairedEndStr = "null";
			if (!(pairedEndRead == null)) {
				pairedEndStr = String.valueOf(pairedEndRead.uniqueID);
			}
			returnString = returnString + " ID:" + this.uniqueID + " PE_ID:" + pairedEndStr; 
		}
		return returnString;
	}
	
}
