/**
 * Copyright (C) 2015 Fikrul Arif
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.alqs.iclib.salat;

import java.util.Date;
import java.util.Iterator;

/**
 * Result of TimeCalculator.
 * 
 * @author fikr4n
 *
 */
public class Times implements Iterable<Date> {

	public static final int FAJR = 0, SUNRISE = 1, ZUHR = 2, ASR = 3, MAGHRIB = 4, ISHA = 5;
	private static final int N = 6;
	
	private boolean useSecond = false;
	private double[] times;
	private long millis;
	
	Times(long millis, double... times) {
		this.times = times;
		this.millis = millis;
	}

	/**
	 * Return the time as {@link Date}.
	 * 
	 * <p>{@link #isUseSecond()} is considered.
	 * 
	 * @param timeName ZUHR, ASR, etc
	 * @return
	 */
	public Date getTime(int timeName) {
		// negative hours will raise exception
		if (isUseSecond())
			return new Date(this.millis + (long) Math.ceil(times[timeName] * 60 * 60) * 1000);
		else
			return new Date(this.millis + (long) Math.ceil(times[timeName] * 60) * 60 * 1000);
	}

	/**
	 * Return the time as hour-minute-second.
	 * 
	 * <p>{@link #isUseSecond()} is considered.
	 * 
	 * @param timeName ZUHR, ASR, etc
	 * @return
	 */
	public Hms getHms(int timeName) {
		if (isUseSecond())
			return new Hms(this.times[timeName]);
		else
			return new Hms(Math.ceil(this.times[timeName] * 60) / 60);
	}
	
	public Date getFajr() {
		return getTime(FAJR);
	}
	public Date getSunrise() {
		return getTime(SUNRISE);
	}
	public Date getZuhr() {
		return getTime(ZUHR);
	}
	public Date getAsr() {
		return getTime(ASR);
	}
	public Date getMaghrib() {
		return getTime(MAGHRIB);
	}
	public Date getIsha() {
		return getTime(ISHA);
	}
	
	/**
	 * Whether second is used, if not it will be zero and minute is rounded to the top (ceil).
	 */
	public boolean isUseSecond() {
		return useSecond;
	}

	public void setUseSecond(boolean useSecond) {
		this.useSecond = useSecond;
	}

	@Override
	public Iterator<Date> iterator() {
		return new Iterator<Date>() {
			
			int nextIndex = 0;

			@Override
			public boolean hasNext() {
				return nextIndex < N;
			}

			@Override
			public Date next() {
				return getTime(nextIndex++);
			}

			@Override
			public void remove() {
				throw new UnsupportedOperationException();
			}
		};
	}

}

@@ -1081,16 +1081,203 @@
 millis;%0A
+%09%09if (times%5BSUNRISE%5D == Double.NEGATIVE_INFINITY %7C%7C times%5BMAGHRIB%5D == Double.POSITIVE_INFINITY) %7B%0A%09%09%09times%5BZUHR%5D = Double.POSITIVE_INFINITY;%0A%09%09%09times%5BASR%5D = Double.POSITIVE_INFINITY;%0A%09%09%7D%0A
 %09%7D%0A%0A%09/**
@@ -1458,16 +1458,132 @@
 Name) %7B%0A
+%09%09double t = times%5BtimeName%5D;%0A%09%09if (t == Double.POSITIVE_INFINITY %7C%7C t == Double.NEGATIVE_INFINITY)%0A%09%09%09return null;%0A
 %09%09// neg
@@ -1683,38 +1683,24 @@
  Math.ceil(t
-imes%5BtimeName%5D
  * 60 * 60) 
@@ -1766,30 +1766,16 @@
 h.ceil(t
-imes%5BtimeName%5D
  * 60) *
@@ -1981,16 +1981,132 @@
 Name) %7B%0A
+%09%09double t = times%5BtimeName%5D;%0A%09%09if (t == Double.POSITIVE_INFINITY %7C%7C t == Double.NEGATIVE_INFINITY)%0A%09%09%09return null;%0A
 %09%09if (is
@@ -2137,35 +2137,16 @@
 ew Hms(t
-his.times%5BtimeName%5D
 );%0A%09%09els
@@ -2180,27 +2180,8 @@
 il(t
-his.times%5BtimeName%5D
  * 6

Handle extreme latitude