package com.iainsproat.simscaletest.primenumbergenerator.core;

import java.time.Duration;
import java.time.Instant;
import java.util.List;

/**
 * Responsible for running the Prime Number Generator strategy
 *
 */
public class PrimeNumberGeneratorStrategyClient {
	
	/**
	 * 
	 * @param requestedStrategy
	 * @param lowerBound
	 * @param upperBound
	 * @return
	 */
	public Result execute(String requestedStrategy, int lowerBound, int upperBound)
	{
		//must be positive numbers
		if(lowerBound < 0)
			lowerBound = 0;
		if(upperBound < 0)
			upperBound = 0;
		//upper bound should always be greater than lower bound.  Rather than failing, we'll be opinionated and swap the two.
		if(lowerBound > upperBound)
		{
			int temp = lowerBound;
			lowerBound = upperBound;
			upperBound = temp;
		}
		
		PrimeNumberGeneratorStrategy strategy = StrategySelector.selectStrategy(requestedStrategy);
		return execute(strategy, lowerBound, upperBound);
	}
	
	/**
	 * Overloaded operator to allow for test injection of Mock strategy
	 */
	public Result execute(PrimeNumberGeneratorStrategy strategy, int lowerBound, int upperBound)
	{		
		Instant start = Instant.now();
		List<Integer> primes = strategy.execute(lowerBound, upperBound);		
		Instant end = Instant.now();
		
		return new Result(start.getEpochSecond(), strategy.getClass().getSimpleName(), lowerBound, upperBound, primes, Duration.between(start, end).getSeconds());
	}
	
	/**
	 * Holds data pertaining to the input parameters and results of a single run of a Prime Number Generator
	 *
	 */
	public class Result{
		private long timeStamp; //FIXME this should be a GUID as timestamps are not guaranteed to be universally unique (despite it being in nanoseconds!).
		private String strategy;
		private int lowerBound;
		private int upperBound;
		private List<Integer> primes;
		private long duration;
		
		public Result(long __timeStamp, String __requestedStrategy, int __lowerBound, int __upperBound, List<Integer> __primeNumbers, long __executionDuration)
		{
			this.timeStamp = __timeStamp;
			this.strategy = __requestedStrategy;
			this.lowerBound = __lowerBound;
			this.upperBound = __upperBound;
			this.primes = __primeNumbers;
			this.duration = __executionDuration;
		}
		
		public long getTimeStamp()
		{
			return this.timeStamp;
		}
		
		public String getRequestedStrategy()
		{
			return this.strategy;
		}
		
		public int getLowerBound()
		{
			return this.lowerBound;
		}
		
		public int getUpperBound()
		{
			return this.upperBound;
		}
		
		public List<Integer> getPrimeNumbers()
		{
			return this.primes;
		}
		
		public long getExecutionDuration()
		{
			return this.duration;
		}
	}
}

@@ -450,678 +450,680 @@
 %7B%0A%09%09
-//must be positive numbers%0A%09%09if(lowerBound %3C 0)%0A%09%09%09lowerBound = 0;%0A%09%09if(upperBound %3C 0)%0A%09%09%09upperBound = 0;%0A%09%09//upper bound should always be greater than lower bound.  Rather than failing, we'll be opinionated and swap the two.%0A%09%09if(lowerBound %3E upperBound)%0A%09%09%7B%0A%09%09%09int temp = lowerBound;%0A%09%09%09lowerBound = upperBound;%0A%09%09%09upperBound = temp;%0A%09%09%7D%0A%09%09%0A%09%09PrimeNumberGeneratorStrategy strategy = StrategySelector.selectStrategy(requestedStrategy);%0A%09%09return execute(strategy, lowerBound, upperBound);%0A%09%7D%0A%09%0A%09/**%0A%09 * Overloaded operator to allow for test injection of Mock strategy%0A%09 */%0A%09public Result execute(PrimeNumberGeneratorStrategy strategy, int lowerBound, int upperBound)%0A%09%7B
+PrimeNumberGeneratorStrategy strategy = StrategySelector.selectStrategy(requestedStrategy);%0A%09%09return execute(strategy, lowerBound, upperBound);%0A%09%7D%0A%09%0A%09/**%0A%09 * Overloaded operator to allow for test injection of Mock strategy%0A%09 */%0A%09public Result execute(PrimeNumberGeneratorStrategy strategy, int lowerBound, int upperBound)%0A%09%7B%09%09%0A%09%09//must be positive numbers%0A%09%09lowerBound = clampToZero(lowerBound);%0A%09%09upperBound = clampToZero(upperBound);%0A%09%09//upper bound should always be greater than lower bound.  Rather than failing, we'll be opinionated and swap the two.%0A%09%09if(lowerBound %3E upperBound)%0A%09%09%7B%0A%09%09%09int temp = lowerBound;%0A%09%09%09lowerBound = upperBound;%0A%09%09%09upperBound = temp;%0A%09%09%7D%0A%09%09
 %09%09%0A%09
@@ -1420,24 +1420,213 @@
 ;%0A%09%7D%0A%09%0A%09/**%0A
+%09 * Ensures the value can never be less than zero%0A%09 * @param value%0A%09 * @return%0A%09 */%0A%09private int clampToZero(int value)%0A%09%7B%0A%09%09if(value %3C 0)%0A%09%09%7B%0A%09%09%09return 0;%0A%09%09%7D%0A%09%09%0A%09%09return value;%0A%09%7D%0A%09%0A%09/**%0A
 %09 * Holds da

Refactor guards