// imported packages
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

public class DownloadFastaFile {

	/**
	 * @param args
	 *            [0]: Uniprot accession number of a protein sequence args[1]:
	 *            Destination
	 * 
	 *            Download a fasta file from uniprot, save the fasta file and
	 *            count the occurrence of each amino acid
	 */

	public static final String URL = "http://www.uniprot.org/uniprot/"; // uniport
																		// url
	//example input Q30201 ./
	public static void main(String[] args) {
		String fastaFile = args[0] + ".fasta"; // append file extension

		downloadFastaFile(fastaFile, args[1]);

		String fasta = readFastaFile(fastaFile);

		int[] occ = countOccurrance(fasta);

		String destination = args[1] + args[0] + ".occ";
		writeOccurranceToFile(occ, destination);
	}

	// download a fasta file from uniprot
	@SuppressWarnings("deprecation")
	public static void downloadFastaFile(String fastaFile, String destination) {

		// create necessary streams
		InputStream inStream = null;
		DataInputStream dInStream;
		String line;
		try {// do not forget the try catch block, we expect some errors here
			URL uniprot = new URL(URL + fastaFile); // complete url
			inStream = uniprot.openStream(); // open file

			// create input stream to read file
			dInStream = new DataInputStream(new BufferedInputStream(inStream));

			// create suitable writer to write the data to a local file
			BufferedWriter writ = new BufferedWriter(new FileWriter(destination
					+ fastaFile));

			/*
			 * read the file line by line and write the data directly to a file,
			 * please note the deprecation warning. This method should not be
			 * used, but we do it just for simplification of the tutorial
			 */
			while ((line = dInStream.readLine()) != null) { // while there are
															// more lines to
															// read
				writ.append(line);
				writ.newLine();
			}
			// close file
			writ.flush();
			writ.close();

			// catch some exceptions, but ignore them
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally { // closes the stream if anything went wrong
			try {
				inStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	}

	// read a locally stored fasta file, but ignore the header
	public static String readFastaFile(String file) {
		String fasta = "";
		BufferedReader buf = null;
		try {
			// create suitable reader
			buf = new BufferedReader(new FileReader(file));
			String line = "";
			while ((line = buf.readLine()) != null) { // while there are 
													//more lines to read
				if (line.startsWith(">"))
					continue; // ignore header line
				fasta += line; // append each line to fasta, just one line is
								// produced
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally { // close reader
			try {
				buf.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return fasta;
	}

	// write the occurence of each amino acid into a local file
	public static void writeOccurranceToFile(int[] occ, String destination) {
		BufferedWriter writ = null; // create writer
		try {
			// initialize writer
			writ = new BufferedWriter(new FileWriter(destination));

			// for each amino acid
			for (int i = 0; i < occ.length; i++) {
				int aa = i + 65; // restore the asciim value
				String line = (char) aa + ":\t" + occ[i]; // cast ascii value to
															// char and write
															// occurance
				writ.append(line); // append line to existing file
				writ.newLine(); // add a newline to write every result in its
								// own line
			}

			// catch some exceptions
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally { // close everything if something went wrong
			try {
				writ.flush();
				writ.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	public static int[] countOccurrance(String fasta) {

		int[] occ = new int[26]; // an array with space for each element of the
									// alphabet
		char[] seq = fasta.toCharArray(); // create a char-array from the string
		for (char c : seq) { // for all loop
			int index = (int) c; // convert the char to an int
			index -= 65; // map the ascii values to a range from 0-26
			occ[index]++; // count accourance
		}
		return occ;
	}

}

