package Evolution;

import java.util.Collections;
import java.util.Vector;

public class Individual {
	
	/**
	 * In this case, the chromosome is an array of integers rather than a string. 
	 */
	private int[] chromosome;
	private double fitness = -1;

	/**
	 * Initializes individual with specific chromosome
	 * 
	 * @param chromosome
	 *            The chromosome to give individual
	 */
	public Individual(int[] chromosome) {
		// Create individualchromosome
		this.chromosome = chromosome;
	}

	/**
	 * Initializes random individual
	 * 
	 * @param chromosomeLength
	 *            The length of the individuals chromosome
	 */
	public Individual(int chromosomeLength, int numRules) {
		// Create random individual
		Vector<Integer> individual = new Vector<Integer>();
		//individual = new int[chromosomeLength];
		
		/**
		 * In this case, we can no longer simply pick 0s and 1s -- we need to
		 * use every city index available. We also don't need to randomize or
		 * shuffle this chromosome, as crossover and mutation will ultimately
		 * take care of that for us.
		 */
		for (int gene = 0; gene < numRules; gene++) {
			individual.add(gene);
		}
		
		Collections.shuffle(individual);
		
		
		int chromossome[] = new int[chromosomeLength];
		
		for (int i=0; i< chromosomeLength; i++) {
			chromossome[i]=individual.get(i);
		}
		
		this.chromosome = chromossome;
	}
	
	public Individual(int chromosomeLength) {
		// Create random individual
		Vector<Integer> individual = new Vector<Integer>();
		//individual = new int[chromosomeLength];
		
		/**
		 * In this case, we can no longer simply pick 0s and 1s -- we need to
		 * use every city index available. We also don't need to randomize or
		 * shuffle this chromosome, as crossover and mutation will ultimately
		 * take care of that for us.
		 */
		for (int gene = 0; gene < chromosomeLength; gene++) {
			individual.add(gene);
		}
		
		Collections.shuffle(individual);
		
		int size = individual.size();
		int chromossome[] = new int[size];
		
		for (int i=0; i< size; i++) {
			chromossome[i]=individual.get(i);
		}
		
		this.chromosome = chromossome;
	}

	/**
	 * Gets individual's chromosome
	 * 
	 * @return The individual's chromosome
	 */
	public int[] getChromosome() {
		return this.chromosome;
	}

	/**
	 * Gets individual's chromosome length
	 * 
	 * @return The individual's chromosome length
	 */
	public int getChromosomeLength() {
		return this.chromosome.length;
	}

	/**
	 * Set gene at offset
	 * 
	 * @param gene
	 * @param offset
	 */
	public void setGene(int offset, int gene) {
		this.chromosome[offset] = gene;
	}

	/**
	 * Get gene at offset
	 * 
	 * @param offset
	 * @return gene
	 */
	public int getGene(int offset) {
		return this.chromosome[offset];
	}

	/**
	 * Store individual's fitness
	 * 
	 * @param fitness
	 *            The individuals fitness
	 */
	public void setFitness(double fitness) {
		this.fitness = fitness;
	}

	/**
	 * Gets individual's fitness
	 * 
	 * @return The individual's fitness
	 */
	public double getFitness() {
		return this.fitness;
	}
	
	public String toString() {
		String output = "";
		for (int gene = 0; gene < this.chromosome.length; gene++) {
			output += this.chromosome[gene] + ",";
		}
		return output;
	}

	/**
	 * Search for a specific integer gene in this individual.
	 * 
	 * For instance, in a Traveling Salesman Problem where cities are encoded as
	 * integers with the range, say, 0-99, this method will check to see if the
	 * city "42" exists.
	 * 
	 * @param gene
	 * @return
	 */
	public boolean containsGene(int gene) {
		for (int i = 0; i < this.chromosome.length; i++) {
			if (this.chromosome[i] == gene) {
				return true;
			}
		}
		return false;
	}


	
}
