package edu.mit.mitmobile2.tour;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import edu.mit.mitmobile2.objs.MapPoint;
import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
public class Tour {
public List<TourItem> getTourList(StartLocation startLocation) {
return getTourList(getSite(startLocation.mSiteGuid));
}
public List<TourItem> getTourList(Site site) {
ArrayList<TourItem> tourItems = new ArrayList<TourItem>();
int currentSiteIndex = site.mSiteIndex;
int lastSiteIndex = currentSiteIndex - 1;
if(currentSiteIndex == 0) {
lastSiteIndex = mSites.size() - 1;
}
boolean finished = false;
while(!finished) {
Site currentSite = mSites.get(currentSiteIndex);
tourItems.add(currentSite);
tourItems.add(currentSite.getExitDirections());
if(currentSiteIndex == lastSiteIndex) {
break;
}
currentSiteIndex++;
if(currentSiteIndex == mSites.size()) {
currentSiteIndex = 0;
}
}
return tourItems;
}
public ArrayList<GeoPoint> getPathGeoPoints() {
ArrayList<GeoPoint> geoPoints = new ArrayList<GeoPoint>();
for(Site site : mSites) {
for(GeoPoint geoPoint : site.getExitDirections().getPath().getGeoPoints()) {
geoPoints.add(geoPoint);
}
}
return geoPoints;
}
public ArrayList<TourMapItem> getDefaultTourMapItems() {
ArrayList<TourMapItem> tourMapItems = new ArrayList<TourMapItem>();
for(Site site : mSites) {
tourMapItems.add(site.getTourMapItem(TourSiteStatus.FUTURE));
}
return tourMapItems;
}
public static ArrayList<TourMapItem> getTourMapItems(List<TourItem> tourItems, int position) {
// determine the currentSite
Site currentSite = null;
while(position > -1) {
if(tourItems.get(position).getClass() == Site.class) {
currentSite = (Site) tourItems.get(position);
break;
}
position--;
}
ArrayList<TourMapItem> tourMapItems = new ArrayList<TourMapItem>();
TourSiteStatus status = TourSiteStatus.VISITED;
for(TourItem tourItem : tourItems) {
if(tourItem.getClass() == Site.class) {
Site site = (Site) tourItem;
// determine the status of the current site
if(status == TourSiteStatus.CURRENT) {
// the previous site was current so move status to future
status = TourSiteStatus.FUTURE;
}
if((currentSite != null) && currentSite.getSiteGuid().equals(site.getSiteGuid())) {
status = TourSiteStatus.CURRENT;
}
tourMapItems.add(site.getTourMapItem(status));
}
}
return tourMapItems;
}
enum TourSiteStatus {
VISITED,
CURRENT,
FUTURE
}
/*
* A simplified representation of Sites that can be passed
* to activities via a bundle
*/
public static class TourMapItem implements Parcelable {
private String mId;
private GeoPoint mGeoPoint;
private String mTitle;
private String mPhotoUrl;
private TourSiteStatus mStatus;
TourMapItem(String id, GeoPoint geoPoint, String title, String photoUrl, TourSiteStatus status) {
mId = id;
mGeoPoint = geoPoint;
mTitle = title;
mPhotoUrl = photoUrl;
mStatus = status;
}
public static TourMapItem readItem(Parcel source) {
String id = source.readString();
GeoPoint geoPoint = source.readParcelable(GeoPoint.class.getClassLoader());
String title = source.readString();
String photoUrl = source.readString();
TourSiteStatus status = TourSiteStatus.values()[source.readInt()];
return new TourMapItem(id, geoPoint, title, photoUrl, status);
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mId);
dest.writeParcelable(mGeoPoint, 0);
dest.writeString(mTitle);
dest.writeString(mPhotoUrl);
dest.writeInt(mStatus.ordinal());
}
public GeoPoint getGeoPoint() {
return mGeoPoint;
}
public String getId() {
return mId;
}
public String getTitle() {
return mTitle;
}
public String getPhotoUrl() {
return mPhotoUrl;
}
public TourSiteStatus getStatus() {
return mStatus;
}
public static interface LocationSupplier {
public Location getLocation();
}
LocationSupplier mLocationSupplier;
public void setLocationSupplier(LocationSupplier locationSupplier) {
mLocationSupplier = locationSupplier;
}
public Float distance() {
if(mLocationSupplier == null) {
return null;
}
Location location = mLocationSupplier.getLocation();
if(location == null) {
return null;
}
float[] distance = new float[1];
double endLatitude = mGeoPoint.getLatitudeE6() / 1E6;
double endLongitude = mGeoPoint.getLongitudeE6() / 1E6;
Location.distanceBetween(location.getLatitude(), location.getLongitude(), endLatitude, endLongitude, distance);
return distance[0];
}
public float distanceBetween(TourMapItem other) {
float[] distance = new float[1];
double startLatitude = this.getGeoPoint().getLatitudeE6() / 1E6;
double startLongitude = this.getGeoPoint().getLongitudeE6() / 1E6;
double endLatitude = other.getGeoPoint().getLatitudeE6() / 1E6;
double endLongitude = other.getGeoPoint().getLongitudeE6() / 1E6;
Location.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude, distance);
return distance[0];
}
}
public static class SiteTourMapItem extends TourMapItem {
private ArrayList<SideTripTourMapItem> mSideTrips = new ArrayList<SideTripTourMapItem>();
SiteTourMapItem(TourMapItem i) {
super(i.mId, i.mGeoPoint, i.mTitle, i.mPhotoUrl, i.mStatus);
}
public static final Parcelable.Creator<SiteTourMapItem> CREATOR = new Parcelable.Creator<SiteTourMapItem>() {
@Override
public SiteTourMapItem createFromParcel(Parcel source) {
TourMapItem item = TourMapItem.readItem(source);
SiteTourMapItem site = new SiteTourMapItem(item);
@SuppressWarnings("unchecked")
ArrayList<SideTripTourMapItem> sideTrips = source.readArrayList(SideTripTourMapItem.class.getClassLoader());
for(SideTripTourMapItem sideTrip : sideTrips) {
sideTrip.setParent(site);
site.addSideTrip(sideTrip);
}
return site;
}
@Override
public SiteTourMapItem[] newArray(int size) {
return new SiteTourMapItem[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeList(mSideTrips);
}
String getSiteGuid() {
return getId();
}
List<SideTripTourMapItem> getSideTrips() {
return mSideTrips;
}
void addSideTrip(SideTripTourMapItem sideTrip) {
mSideTrips.add(sideTrip);
}
}
public static class SideTripTourMapItem extends TourMapItem {
SiteTourMapItem mParent;
boolean mIsOnSite; // (otherwise its on directions)
SideTripTourMapItem(String id, GeoPoint geoPoint, String title, String photoUrl, boolean isOnSite) {
super(id, geoPoint, title, photoUrl, TourSiteStatus.FUTURE);
mIsOnSite = isOnSite;
}
SideTripTourMapItem(TourMapItem i, boolean isOnSite) {
super(i.mId, i.mGeoPoint, i.mTitle, i.mPhotoUrl, i.mStatus);
mIsOnSite = isOnSite;
}
public static final Parcelable.Creator<SideTripTourMapItem> CREATOR = new Parcelable.Creator<SideTripTourMapItem>() {
@Override
public SideTripTourMapItem createFromParcel(Parcel source) {
TourMapItem item = TourMapItem.readItem(source);
int isOnSiteFlag = source.readInt();
return new SideTripTourMapItem(item, (isOnSiteFlag == 1));
}
@Override
public SideTripTourMapItem[] newArray(int size) {
return new SideTripTourMapItem[size];
}
};
@Override
public int describeContents() {
return 0;
}
public void setParent(SiteTourMapItem mapItem) {
mParent = mapItem;
}
public SiteTourMapItem getParent() {
return mParent;
}
@Override
public String getId() {
String delimiter = mIsOnSite ? "_" : "_directions_";
return mParent.getSiteGuid() + delimiter + super.getId();
}
public String getSideTripId() {
return super.getId();
}
public boolean isOnSideTrip() {
return mIsOnSite;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(mIsOnSite ? 1 : 0);
}
}
abstract public static class TourItem {
abstract String getLabel();
abstract String getTitle();
abstract TourItemContent getContent();
abstract Path getPath();
abstract PhotoInfo getPhotoInfo();
public abstract String getAudioUrl();
}
public static class PhotoInfo {
String mPhotoUrl;
String mPhotoLabel;
PhotoInfo(String photoUrl, String photoLabel) {
mPhotoUrl = photoUrl;
mPhotoLabel = photoLabel;
}
public String getPhotoUrl() {
return mPhotoUrl;
}
public String getPhotoLabel() {
return mPhotoLabel;
}
}
public static class TourItemContent {
HashMap<String, SideTrip> mSideTrips = new HashMap<String, SideTrip>();
ArrayList<TourItemContentNode> mContentNodes = new ArrayList<TourItemContentNode>();
public void addSideTrip(SideTrip sideTrip) {
mContentNodes.add(sideTrip);
mSideTrips.put(sideTrip.getId(), sideTrip);
}
public void addHtml(String html) {
mContentNodes.add(new HtmlContentNode(html));
}
public List<TourItemContentNode> getContentNodes() {
return mContentNodes;
}
public SideTrip getSideTrip(String id) {
return mSideTrips.get(id);
}
}
abstract public static class TourItemContentNode {
abstract String getHtml();
};
public static class HtmlContentNode extends TourItemContentNode {
private String mHtml;
HtmlContentNode(String html) {
mHtml = html;
}
@Override
public String getHtml() {
return mHtml;
}
}
public static class SideTrip extends TourItemContentNode {
String mId;
String mHtml;
String mTitle;
String mPhotoUrl;
String mThumbnailUrl;
String mAudioUrl;
GeoPoint mGeoPoint;
SideTrip(String id, String title, String html,
String photoUrl, String thumbnailUrl,
String audioUrl, GeoPoint geoPoint) {
mId = id;
mTitle = title;
mHtml = html;
mPhotoUrl = photoUrl;
mThumbnailUrl = thumbnailUrl;
mAudioUrl = audioUrl;
mGeoPoint = geoPoint;
}
public String getId() {
return mId;
}
public String getTitle() {
return mTitle;
}
@Override
public String getHtml() {
return mHtml;
}
public String getPhotoUrl() {
return mPhotoUrl;
}
public String getThumbnailUrl() {
return mThumbnailUrl;
}
public String getAudioUrl() {
return mAudioUrl;
}
public GeoPoint getGeoPoint() {
return mGeoPoint;
}
public SideTripTourMapItem getTourMapItem(boolean isOnSite) {
return new SideTripTourMapItem(mId, mGeoPoint, mTitle, mThumbnailUrl, isOnSite);
}
}
public static class Path {
private ArrayList<GeoPoint> mGeoPoints = new ArrayList<GeoPoint>();
private int mZoom;
public Path(int zoom) {
mZoom = zoom;
}
public void addGeoPoint(GeoPoint geoPoint) {
mGeoPoints.add(geoPoint);
}
public List<GeoPoint> getGeoPoints() {
return mGeoPoints;
}
public int getZoom() {
return mZoom;
}
}
public class TourHeader {
private String mGuid;
private String mTitle;
private String mDescriptionTop;
private String mDescriptionBottom;
public TourHeader(String guid, String title, String descriptionTop, String descriptionBottom) {
mGuid = guid;
mTitle = title;
mDescriptionTop = descriptionTop;
mDescriptionBottom = descriptionBottom;
}
public String getGuid() {
return mGuid;
}
public String getDescriptionTop() {
return mDescriptionTop;
}
public String getDescriptionBottom() {
return mDescriptionBottom;
}
public String getTitle() {
return mTitle;
}
}
private TourHeader mHeader;
public Tour(TourHeader header) {
mHeader = header;
}
public Tour(String guid, String title, String topHtml, String bottomHtml) {
mHeader = new TourHeader(guid, title, topHtml, bottomHtml);
}
public TourHeader getHeader() {
return mHeader;
}
public static class FooterLink {
private String mTitle;
private String mUrl;
FooterLink(String title, String url) {
mUrl = url;
mTitle = title;
}
public String getTitle() {
return mTitle;
}
public String getUrl() {
return mUrl;
}
}
public class TourFooter {
private String mFeedbackSubject;
private ArrayList<FooterLink> mLinks = new ArrayList<FooterLink>();
public void setFeedbackSubject(String feedbackSubject) {
mFeedbackSubject = feedbackSubject;
}
public String getFeedbackSubject() {
return mFeedbackSubject;
}
public void addLink(String title, String url) {
mLinks.add(new FooterLink(title, url));
}
public List<FooterLink> getLinks() {
return mLinks;
}
}
private TourFooter mFooter = new TourFooter();
public void setFeedbackSubject(String feedbackSubject) {
mFooter.setFeedbackSubject(feedbackSubject);
}
public TourFooter getFooter() {
return mFooter;
}
private ArrayList<Site> mSites = new ArrayList<Site>();
public Site addSite(String guid, String name, String photoUrl, String thumbnailUrl, String audioUrl, GeoPoint geoPoint) {
Site site = new Site(mSites.size(), guid, name, photoUrl, thumbnailUrl, audioUrl, geoPoint);
mSites.add(site);
return site;
}
public List<Site> getSites() {
return mSites;
}
public Site getSite(String guid) {
for(Site site: mSites) {
if(site.mSiteGuid.equals(guid)) {
return site;
}
}
return null;
}
public class Site extends TourItem {
private int mSiteIndex;
private String mSiteGuid;
private String mName;
private TourItemContent mContent;
private PhotoInfo mPhotoInfo;
private String mThumbnailUrl;
private String mAudioUrl;
private GeoPoint mGeoPoint;
public Site(int siteIndex, String guid, String name, String photoUrl, String thumbnailUrl, String audioUrl, GeoPoint geoPoint) {
mSiteIndex = siteIndex;
mSiteGuid = guid;
mName = name;
mContent = new TourItemContent();
mPhotoInfo = new PhotoInfo(photoUrl, name);
mThumbnailUrl = thumbnailUrl;
mAudioUrl = audioUrl;
mGeoPoint = geoPoint;
}
public GeoPoint getGeoPoint() {
return mGeoPoint;
}
public String getSiteGuid() {
return mSiteGuid;
}
public String getName() {
return mName;
}
private Directions mExitDirections;
public Directions setExitDirections(String title, String destinationGuid, int zoom) {
mExitDirections = new Directions(this, title, destinationGuid, zoom);
return mExitDirections;
}
public Directions getExitDirections() {
return mExitDirections;
}
// TourItem getters
@Override
TourItemContent getContent() {
return mContent;
}
@Override
Path getPath() {
return null;
}
@Override
PhotoInfo getPhotoInfo() {
return mPhotoInfo;
}
@Override
String getTitle() {
return mName;
}
@Override
String getLabel() {
return mName;
}
public SiteTourMapItem getTourMapItem(TourSiteStatus status) {
TourMapItem item = new TourMapItem(mSiteGuid, mGeoPoint, mName, mThumbnailUrl, status);
SiteTourMapItem siteItem = new SiteTourMapItem(item);
// loop thru sidetrips
for(TourItemContentNode node : mContent.mContentNodes) {
if(node.getClass() == SideTrip.class) {
SideTrip sideTrip = (SideTrip) node;
siteItem.addSideTrip(sideTrip.getTourMapItem(true));
}
}
// loop thru sidetrips on the directions
for(TourItemContentNode node : mExitDirections.getContent().getContentNodes()) {
if(node.getClass() == SideTrip.class) {
SideTrip sideTrip = (SideTrip) node;
siteItem.addSideTrip(sideTrip.getTourMapItem(false));
}
}
return siteItem;
}
public SideTrip getSideTrip(String sidetripId, boolean isOnSite) {
TourItemContent content;
if(isOnSite) {
content = mContent;
} else {
content = mExitDirections.getContent();
}
// loop thru content nodes
for(TourItemContentNode node : content.mContentNodes) {
if(node.getClass() == SideTrip.class) {
SideTrip sideTrip = (SideTrip) node;
if(sideTrip.getId().equals(sidetripId)) {
return sideTrip;
}
}
}
return null;
}
public String getThumbnailUrl() {
return mThumbnailUrl;
}
@Override
public
String getAudioUrl() {
return mAudioUrl;
}
}
public class Directions extends TourItem {
private Site mSource;
private String mTitle;
private TourItemContent mContent;
private Path mPath;
private String mDestinationGuid;
private String mPhotoUrl;
private String mAudioUrl;
Directions(Site source, String title, String destinationGuid, int zoom) {
mSource = source;
mTitle = title;
mContent = new TourItemContent();
mPath = new Path(zoom);
mDestinationGuid = destinationGuid;
}
@Override
public String getTitle() {
return mTitle;
}
@Override
public TourItemContent getContent() {
return mContent;
}
public String getDestinationGuid() {
return mDestinationGuid;
}
public void setPath(Path path) {
mPath = path;
}
public void setPhotoUrl(String photoUrl) {
mPhotoUrl = photoUrl;
}
public void setAudioUrl(String audioUrl) {
mAudioUrl = audioUrl;
}
@Override
Path getPath() {
return mPath;
}
@Override
PhotoInfo getPhotoInfo() {
if(mPhotoUrl != null) {
return new PhotoInfo(mPhotoUrl, getSite(mDestinationGuid).getTitle());
} else {
return getSite(mDestinationGuid).getPhotoInfo();
}
}
@Override
String getLabel() {
return "Walk to " + getSite(mDestinationGuid).getLabel();
}
@Override
public
String getAudioUrl() {
return mAudioUrl;
}
public Site getSource() {
return mSource;
}
}
private String mStartLocationsHeader;
public void setStartLocationsHeader(String header) {
mStartLocationsHeader = header;
}
public String getStartLocationsHeader() {
return mStartLocationsHeader;
}
private ArrayList<StartLocation> mStartLocations = new ArrayList<StartLocation>();
public StartLocation addStartLocation(String title, String locationId, String siteGuid, String content, String photoUrl, GeoPoint geoPoint) {
StartLocation startLocation = new StartLocation(title, locationId, siteGuid, content, photoUrl, geoPoint);
mStartLocations.add(startLocation);
return startLocation;
}
public List<StartLocation> getStartLocations() {
return mStartLocations;
}
public StartLocation getStartLocation(String id) {
for(StartLocation startLocation : mStartLocations) {
if(startLocation.mLocationId.equals(id)) {
return startLocation;
}
}
return null;
}
public class StartLocation {
private String mTitle;
private String mSiteGuid;
private String mLocationId;
private String mContent;
private String mPhotoUrl;
private GeoPoint mGeoPoint;
private float mDistance;
public StartLocation(String title, String locationId, String siteGuid, String content, String photoUrl, GeoPoint geoPoint) {
mTitle = title;
mLocationId = locationId;
mSiteGuid = siteGuid;
mContent = content;
mPhotoUrl = photoUrl;
mGeoPoint = geoPoint;
}
public String getTitle() {
return mTitle;
}
public String getSiteGuid() {
return mSiteGuid;
}
public String getLocationId() {
return mLocationId;
}
public String getContent() {
return mContent;
}
public String getPhotoUrl() {
return mPhotoUrl;
}
public void setGeoPoint(GeoPoint geoPoint) {
mGeoPoint = geoPoint;
}
public GeoPoint getGeoPoint() {
return mGeoPoint;
}
public float getDistance() {
return mDistance;
}
public void setDistance(float distance) {
mDistance = distance;
}
}
public static class GeoPoint implements Parcelable {
private int mLatitudeE6;
private int mLongitudeE6;
public GeoPoint(int latitudeE6, int longitudeE6) {
mLatitudeE6 = latitudeE6;
mLongitudeE6 = longitudeE6;
}
public int getLatitudeE6() {
return mLatitudeE6;
}
public int getLongitudeE6() {
return mLongitudeE6;
}
public MapPoint getMapPoint() {
return new MapPoint(mLatitudeE6 / 1E6, mLongitudeE6 / 1E6);
}
public static final Parcelable.Creator<GeoPoint> CREATOR = new Parcelable.Creator<GeoPoint>() {
@Override
public GeoPoint createFromParcel(Parcel source) {
int latitudeE6 = source.readInt();
int longitudeE6 = source.readInt();
return new GeoPoint(latitudeE6, longitudeE6);
}
@Override
public GeoPoint[] newArray(int size) {
return new GeoPoint[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(getLatitudeE6());
dest.writeInt(getLongitudeE6());
}
}
}