/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
*
* 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 org.onebusaway.webapp.gwt.oba_application.control;
import java.util.ArrayList;
import java.util.List;
import org.onebusaway.geospatial.model.CoordinatePoint;
import org.onebusaway.transit_data.model.oba.LocalSearchResult;
import org.onebusaway.transit_data.model.tripplanning.ConstraintsBean;
import org.onebusaway.transit_data.model.tripplanning.ItinerariesBean;
import org.onebusaway.transit_data.model.tripplanning.TransitShedConstraintsBean;
import org.onebusaway.webapp.gwt.common.context.Context;
import org.onebusaway.webapp.gwt.common.context.ContextHelper;
import org.onebusaway.webapp.gwt.common.context.ContextManager;
import org.onebusaway.webapp.gwt.common.control.Place;
import org.onebusaway.webapp.gwt.common.control.PlaceSearch;
import org.onebusaway.webapp.gwt.common.control.PlaceSearchListener;
import org.onebusaway.webapp.gwt.common.model.ModelEventSink;
import org.onebusaway.webapp.gwt.common.model.ModelListener;
import org.onebusaway.webapp.gwt.oba_application.control.state.AddressLookupErrorState;
import org.onebusaway.webapp.gwt.oba_application.control.state.SearchLocationUpdatedState;
import org.onebusaway.webapp.gwt.oba_application.control.state.TripPlansState;
import org.onebusaway.webapp.gwt.oba_application.model.FilteredResultsModel;
import org.onebusaway.webapp.gwt.oba_application.model.LocationQueryModel;
import org.onebusaway.webapp.gwt.oba_application.model.PagedResultsModel;
import org.onebusaway.webapp.gwt.oba_application.model.ResultsModel;
import org.onebusaway.webapp.gwt.oba_application.model.TimedLocalSearchResult;
import org.onebusaway.webapp.gwt.oba_application.search.LocalSearchProvider;
import org.onebusaway.webapp.gwt.tripplanner_library.model.TripPlanModel;
import org.onebusaway.webapp.gwt.where_library.rpc.WebappServiceAsync;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.geom.LatLngBounds;
import com.google.gwt.user.client.rpc.AsyncCallback;
public abstract class CommonControlImpl implements CommonControl {
protected ModelEventSink<StateEvent> _stateEvents;
/*****************************************************************************
* Model Layer
****************************************************************************/
protected ResultsModel _resultsModel;
private FilteredResultsModel _filteredResultsModel;
private PagedResultsModel _pagedResultsModel;
private TripPlanModel _tripModel;
/****
* Control Layer
****/
protected ContextHelper _contextHelper;
private MinTransitTimeResultHandler _minTransitTimeResultHandler;
protected LocalSearchProvider _localSearchProvider;
protected int _contextIndex = 0;
public void setStateEvents(ModelEventSink<StateEvent> events) {
_stateEvents = events;
}
public void setContextManager(ContextManager contextManager) {
_contextHelper = new ContextHelper(contextManager);
}
public ModelListener<LocationQueryModel> getQueryModelHandler() {
return new LocationQueryHandler();
}
public void setResultsModel(ResultsModel model) {
_resultsModel = model;
}
public void setFilteredResultsModel(FilteredResultsModel filteredResultsModel) {
_filteredResultsModel = filteredResultsModel;
}
public void setPagedResultsModel(PagedResultsModel model) {
_pagedResultsModel = model;
}
public void setTripPlanModel(TripPlanModel tripModel) {
_tripModel = tripModel;
}
public void setMinTransitTimeResultHandler(MinTransitTimeResultHandler handler) {
_minTransitTimeResultHandler = handler;
}
public void setLocalSearchProvider(LocalSearchProvider provider) {
_localSearchProvider = provider;
}
/*****************************************************************************
* {@link OneBusAwayStandardControl} Interface
****************************************************************************/
public void handleContext(Context context) {
if (context.hasParam("_")) {
try {
_contextIndex = Integer.parseInt(context.getParam("_")) + 1;
} catch (NumberFormatException ex) {
}
}
}
public void filterResults(Filter<TimedLocalSearchResult> filter) {
_filteredResultsModel.setFilter(filter);
}
public void setActiveSearchResult(TimedLocalSearchResult result) {
_pagedResultsModel.setSelectedResult(result);
}
public void clearActiveSearchResult() {
_pagedResultsModel.clearActiveSearchResult();
}
public void getDirectionsToPlace(LocalSearchResult place) {
_stateEvents.fireModelChange(new StateEvent(new TripPlansState()));
WebappServiceAsync service = WebappServiceAsync.SERVICE;
LatLng fromPoint = getQueryLocation();
CoordinatePoint from = new CoordinatePoint(fromPoint.getLatitude(),
fromPoint.getLongitude());
CoordinatePoint to = new CoordinatePoint(place.getLat(), place.getLon());
long time = getQueryTime();
TransitShedConstraintsBean constraints = getQueryConstraints();
service.getTripsBetween(from, to, time, constraints.getConstraints(),
new TripPlanHandler());
}
/****
* Protected Methods
****/
protected abstract LatLng getQueryLocation();
protected abstract long getQueryTime();
protected abstract TransitShedConstraintsBean getQueryConstraints();
protected abstract void setQueryLocationLookupResult(Place place);
/*****************************************************************************
* Private Methods
****************************************************************************/
private class LocationQueryHandler implements
ModelListener<LocationQueryModel> {
public void handleUpdate(LocationQueryModel model) {
if (model.getLocation() == null) {
PlaceSearch search = new PlaceSearch();
LatLngBounds view = LatLngBounds.newInstance();
view.extend(LatLng.newInstance(47.97430795395781, -121.79454591726969));
view.extend(LatLng.newInstance(47.152554314370924, -122.50104172828858));
search.query(model.getLocationQuery(), new GeocoderResultHandler(),
view);
} else {
_stateEvents.fireModelChange(new StateEvent(
new SearchLocationUpdatedState()));
LatLng location = model.getLocation();
long time = model.getTime();
TransitShedConstraintsBean constraints = model.getConstraints();
ConstraintsBean c = constraints.getConstraints();
WebappServiceAsync service = WebappServiceAsync.SERVICE;
int timeSegmentSize = (c.getMaxTripDuration() / 600);
CoordinatePoint p = new CoordinatePoint(location.getLatitude(),
location.getLongitude());
service.getMinTravelTimeToStopsFrom(p, time, constraints,
timeSegmentSize, _minTransitTimeResultHandler);
}
}
}
private class GeocoderResultHandler implements PlaceSearchListener {
public void handleSingleResult(Place place) {
setQueryLocationLookupResult(place);
}
public void handleNoResult() {
_stateEvents.fireModelChange(new StateEvent(new AddressLookupErrorState(
new ArrayList<Place>())));
}
public void handleMultipleResults(List<Place> locations) {
_stateEvents.fireModelChange(new StateEvent(new AddressLookupErrorState(
locations)));
}
public void handleError() {
_stateEvents.fireModelChange(new StateEvent(new AddressLookupErrorState(
new ArrayList<Place>())));
}
}
private class TripPlanHandler implements AsyncCallback<ItinerariesBean> {
public void onSuccess(ItinerariesBean trips) {
_tripModel.setTripPlans(trips);
}
public void onFailure(Throwable ex) {
ex.printStackTrace();
}
}
}