package com.hourlyweather.forecast;
import java.io.Serializable;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Hours;
public class HourlyForecast implements Serializable {
private static final long serialVersionUID = 1L;
Double lat, lon;
ForecastHour[] forecastHours;
DateTime start;
int hours;
DateTimeZone timeZone;
public HourlyForecast(double lat, double lon, DateTime start, int hours) {
this.lat = lat;
this.lon = lon;
this.start = start;
this.hours = hours;
timeZone = DateTimeZone.getDefault();
forecastHours = new ForecastHour[hours];
}
public HourlyForecast(double lat, double lon, DateTime start, int hours, DateTimeZone timeZone) {
this(lat, lon, start, hours);
if(timeZone != null) {
this.timeZone = timeZone;
this.start = start.withZone(timeZone);
}
}
public HourlyForecast(double lat, double lon, DateTime start, int hours, Integer timeZoneOffset) {
this(lat, lon, start, hours);
if(timeZoneOffset != null) {
timeZone = DateTimeZone.forOffsetHours(timeZoneOffset);
this.start = start.withZone(timeZone);
}
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLon() {
return lon;
}
public void setLon(Double lon) {
this.lon = lon;
}
public ForecastHour[] getForecastHours() {
return forecastHours;
}
public void setForecastHours(ForecastHour[] forecastHours) {
this.forecastHours = forecastHours;
}
public DateTime getStart() {
return start;
}
public void setStart(DateTime start) {
this.start = start;
}
public int getHours() {
return hours;
}
public void setHours(int hours) {
this.hours = hours;
}
public DateTimeZone getTimeZone() {
return timeZone;
}
public int getSize() {
return hours;
}
public ForecastHour get(int i) {
return forecastHours[i];
}
private int getHourIndex(DateTime dateTime) {
// calculate the difference from the forecast time to the
// start period to map it to the array
int hoursFromStart = Hours.hoursBetween(start, dateTime).getHours();
if (hoursFromStart > -1 && hoursFromStart < hours)
// this hour is relevant to our forecast
return hoursFromStart;
// if the hour falls outside the forecast then return -1
return Hours.hoursBetween(start, dateTime).getHours();
}
public void set(int i, ForecastHour forecastHour) {
if (i < hours && i >= 0)
forecastHours[i] = forecastHour;
}
/**
* Convenience method to add a forecast hour using an hour span
*
* @param i
* the hour index
* @param forecastHour
*/
public void add(DateTime from, DateTime to, ForecastHour forecastHour) {
// check if these hours apply to our range
if (!to.isAfter(start))
return;
// use the forecast start if the spans starts before our range
if (from.isBefore(start))
from = start;
int spanStartIndex = getHourIndex(from);
// if the span is after our
if (spanStartIndex > hours)
return;
int spanEndIndex = Hours.hoursBetween(from, to).getHours()
+ spanStartIndex;
// make sure the span end isn't past our hour range
if (spanEndIndex >= hours)
spanEndIndex = hours - 1;
for (int i = spanStartIndex; i <= spanEndIndex; i++)
if (forecastHours[i] == null)
forecastHours[i] = forecastHour;
else
forecastHours[i] = new ForecastHour(forecastHours[i],
forecastHour);
}
/**
* mark an hour as containing a sun change dependent on isGoingUp
*
* @param isGoingUp
* @param hourIndex
*/
public void markHourAsSunChange(boolean isGoingUp, int hourIndex) {
if (hourIndex < hours && hourIndex >= 0) {
if (forecastHours[hourIndex] == null)
forecastHours[hourIndex] = new ForecastHour();
forecastHours[hourIndex].setSunUp(isGoingUp);
}
}
/**
* Returns if the forecast is populated with at least one hour
*
* @return
*/
public boolean isPopulated() {
for (ForecastHour forecastHour : forecastHours)
if (forecastHour != null)
return true;
return false;
}
}