/*
This file is part of RateBeer For Android.
RateBeer for Android is free software: you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either
version 3 of the License, or (at your option) any later version.
RateBeer for Android is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RateBeer for Android. If not, see
<http://www.gnu.org/licenses/>.
*/
package com.ratebeer.android.gui.fragments;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import android.content.Context;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.net.Uri;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.googlecode.androidannotations.annotations.AfterViews;
import com.googlecode.androidannotations.annotations.EFragment;
import com.googlecode.androidannotations.annotations.FragmentArg;
import com.googlecode.androidannotations.annotations.InstanceState;
import com.googlecode.androidannotations.annotations.OptionsItem;
import com.googlecode.androidannotations.annotations.OptionsMenu;
import com.googlecode.androidannotations.annotations.ViewById;
import com.ratebeer.android.R;
import com.ratebeer.android.api.ApiMethod;
import com.ratebeer.android.api.CommandSuccessResult;
import com.ratebeer.android.api.HttpHelper;
import com.ratebeer.android.api.command.Country;
import com.ratebeer.android.api.command.GetAliasedBeerCommand;
import com.ratebeer.android.api.command.GetBrewerBeersCommand;
import com.ratebeer.android.api.command.GetBrewerDetailsCommand;
import com.ratebeer.android.api.command.GetBrewerDetailsCommand.BrewerDetails;
import com.ratebeer.android.api.command.SearchBeersCommand;
import com.ratebeer.android.api.command.SearchBeersCommand.BeerSearchResult;
import com.ratebeer.android.api.command.SearchBeersCommand.BeerSearchResultComparator;
import com.ratebeer.android.api.command.SearchBeersCommand.BeerSearchResultComparator.SortBy;
import com.ratebeer.android.api.command.State;
import com.ratebeer.android.app.location.LocationUtils;
import com.ratebeer.android.gui.components.RateBeerMapFragment;
import com.ratebeer.android.gui.components.helpers.ActivityUtil;
import com.ratebeer.android.gui.components.helpers.ArrayAdapter;
import com.viewpagerindicator.TabPageIndicator;
import de.neofonie.mobile.app.android.widget.crouton.Crouton;
import de.neofonie.mobile.app.android.widget.crouton.Style;
@EFragment(R.layout.fragment_brewerview)
@OptionsMenu({R.menu.refresh, R.menu.brewer, R.menu.share})
public class BrewerViewFragment extends RateBeerMapFragment {
protected static final String BASE_URI_FACEBOOK = "https://www.facebook.com/%1$s";
protected static final String BASE_URI_TWITTER = "https://twitter.com/%1$s";
@FragmentArg
@InstanceState
protected int brewerId;
@InstanceState
protected BrewerDetails brewer;
@InstanceState
protected ArrayList<BeerSearchResult> beers = null;
@ViewById
protected ViewPager pager;
@ViewById
protected TabPageIndicator titles;
protected ListView beersView;
protected TextView nameText, descriptionText;
protected Button locationText, websiteButton, facebookButton, twitterButton;
public BrewerViewFragment() {
}
@AfterViews
public void init() {
pager.setAdapter(new BrewerPagerAdapter());
titles.setViewPager(pager);
beersView.setOnItemClickListener(onBeerSelected);
if (brewer != null) {
publishDetails(brewer);
publishBeers(beers);
} else {
refreshDetails();
refreshBeers();
}
}
@OptionsItem(R.id.menu_refresh)
protected void onRefresh() {
refreshDetails();
refreshBeers();
}
@OptionsItem(R.id.menu_sortby)
protected void onSort() {
new BrewerBeersSortDialog(this).show(getActivity().getSupportFragmentManager(), null);
}
@OptionsItem(R.id.menu_share)
protected void onShare() {
if (brewer != null) {
// Start a share intent for this event
Intent s = new Intent(Intent.ACTION_SEND);
s.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
s.setType("text/plain");
s.putExtra(Intent.EXTRA_TEXT,
getString(R.string.brewers_share, brewer.brewerName, Integer.toString(brewer.brewerId)));
startActivity(Intent.createChooser(s, getString(R.string.brewers_sharebrewer)));
}
}
private void refreshDetails() {
execute(new GetBrewerDetailsCommand(getUser(), brewerId));
}
private void refreshBeers() {
execute(new GetBrewerBeersCommand(getUser(), brewerId, getUser() != null ? getUser().getUserID()
: SearchBeersCommand.NO_USER));
}
private OnClickListener onLocationClick = new OnClickListener() {
@Override
public void onClick(View v) {
// Try to start Google Maps at the location
Intent intent = new Intent(Intent.ACTION_VIEW);
try {
intent.setData(Uri.parse("geo:0,0?q="
+ URLEncoder.encode((brewer.address != null ? brewer.address : "")
+ (brewer.city != null ? " " + brewer.city : ""), HttpHelper.UTF8)));
} catch (UnsupportedEncodingException e) {
}
startActivity(intent);
}
};
private OnClickListener onWebsiteClick = new OnClickListener() {
@Override
public void onClick(View v) {
String web = brewer.website;
if (!web.startsWith("http://")) {
// http:// should be explicit in the web address
web = "http://" + web;
}
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(web));
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
if (ActivityUtil.isIntentAvailable(getActivity(), i)) {
startActivity(i);
} else {
publishException(null, getString(R.string.error_invalidurl));
}
}
};
private OnClickListener onFacebookClick = new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(String.format(BASE_URI_FACEBOOK, brewer.facebook))));
}
};
private OnClickListener onTwitterClick = new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(String.format(BASE_URI_TWITTER, brewer.twitter))));
}
};
private OnItemClickListener onBeerSelected = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
BeerSearchResult item = ((BrewerBeersAdapter) beersView.getAdapter()).getItem(position);
if (item.isAlias) {
// No aliased beer id: try to parse it instead
Crouton.makeText(getActivity(), R.string.search_aliasedbeer_redirect, Style.INFO).show();
execute(new GetAliasedBeerCommand(getUser(), item.beerId));
return;
}
load(BeerViewFragment_.builder().beerId(item.beerId).beerName(item.beerName).ratingsCount(item.rateCount)
.build());
}
};
@Override
public void onTaskSuccessResult(CommandSuccessResult result) {
if (result.getCommand().getMethod() == ApiMethod.GetBrewerDetails) {
publishDetails(((GetBrewerDetailsCommand) result.getCommand()).getDetails());
} else if (result.getCommand().getMethod() == ApiMethod.GetBrewerBeers) {
publishBeers(((GetBrewerBeersCommand) result.getCommand()).getBeers());
} else if (result.getCommand().getMethod() == ApiMethod.GetAliasedBeer) {
// Alias found: redirect to beer details
load(BeerViewFragment_.builder().beerId(((GetAliasedBeerCommand) result.getCommand()).getAliasedBeerId())
.build());
}
}
public void setSortOrder(SortBy sortBy) {
// Sort and publish again (which stores and shows the updated list)
Collections.sort(beers, new BeerSearchResultComparator(sortBy));
publishBeers(beers);
}
private void publishDetails(BrewerDetails details) {
this.brewer = details;
if (details == null) {
return;
}
// Show details
setDetails();
}
private void publishBeers(ArrayList<BeerSearchResult> beers) {
this.beers = beers;
if (beersView.getAdapter() == null) {
beersView.setAdapter(new BrewerBeersAdapter(getActivity(), beers));
} else {
((BrewerBeersAdapter) beersView.getAdapter()).replace(beers);
}
}
private void setDetails() {
nameText.setText(brewer.brewerName);
descriptionText.setText(brewer.description == null? "": brewer.description);
String state = "";
String country = "";
if (brewer.countryID > 0 && Country.ALL_COUNTRIES.containsKey(brewer.countryID)) {
country = "\n" + Country.ALL_COUNTRIES.get(brewer.countryID).getName();
if (brewer.stateID > 0 && State.ALL_STATES.containsKey(brewer.countryID)) {
Map<Integer, State> states = State.ALL_STATES.get(brewer.countryID);
if (states.containsKey(brewer.stateID)) {
state = ", " + states.get(brewer.stateID).getName();
}
}
}
locationText.setText(brewer.address + "\n" + brewer.city + state + country);
websiteButton.setText(brewer.website);
//facebookButton.setText(brewer.facebook); // Just use the text 'Facebook', because often this isn't a nice looking name
twitterButton.setText("@" + brewer.twitter);
// Make fields visible too
descriptionText.setVisibility(brewer.description.equals("") || brewer.description.equals("null")? View.GONE: View.VISIBLE);
locationText.setVisibility(View.VISIBLE);
websiteButton.setVisibility(brewer.website.equals("") || brewer.website.equals("null")? View.GONE: View.VISIBLE);
facebookButton.setVisibility(brewer.facebook.equals("") || brewer.facebook.equals("null")? View.GONE: View.VISIBLE);
twitterButton.setVisibility(brewer.twitter.equals("") || brewer.twitter.equals("null")? View.GONE: View.VISIBLE);
if (getMap() != null) {
try {
// Use Geocoder to look up the coordinates of this brewer
try {
List<Address> point = new Geocoder(getActivity()).getFromLocationName(brewer.address + " "
+ brewer.city, 1);
if (point.size() <= 0) {
// Cannot find address: hide the map
getMapView().setVisibility(View.GONE);
} else {
// Found a location! Center the map here
LocationUtils.initGoogleMap(getMap(), point.get(0).getLatitude(), point.get(0).getLongitude());
getMap().addMarker(new MarkerOptions()
.position(new LatLng(point.get(0).getLatitude(), point.get(0).getLongitude()))
.title(brewer.brewerName).snippet(brewer.city)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_VIOLET)));
getMapView().setVisibility(View.VISIBLE);
}
} catch (IOException e) {
// Can't connect to Geocoder server: hide the map
getMapView().setVisibility(View.GONE);
}
} catch (NoSuchMethodError e) {
// Geocoder is not available at all: hide the map
getMapView().setVisibility(View.GONE);
}
}
}
private class BrewerBeersAdapter extends ArrayAdapter<BeerSearchResult> {
public BrewerBeersAdapter(Context context, List<BeerSearchResult> objects) {
super(context, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the right view, using a ViewHolder
BeerViewHolder holder;
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_beersearchresult, null);
holder = new BeerViewHolder();
holder.beer = (TextView) convertView.findViewById(R.id.beer);
holder.overall = (TextView) convertView.findViewById(R.id.overall);
holder.count = (TextView) convertView.findViewById(R.id.count);
holder.rated = (TextView) convertView.findViewById(R.id.rated);
holder.retired = (TextView) convertView.findViewById(R.id.retired);
holder.alias = (TextView) convertView.findViewById(R.id.alias);
convertView.setTag(holder);
} else {
holder = (BeerViewHolder) convertView.getTag();
}
// Bind the data
BeerSearchResult item = getItem(position);
holder.beer.setText(item.beerName);
holder.overall.setText((item.overallPerc >= 0 ? String.format("%.0f", item.overallPerc) : "?"));
holder.count.setText(Integer.toString(item.rateCount) + " " + getString(R.string.details_ratings));
holder.rated.setVisibility(item.isRated ? View.VISIBLE : View.GONE);
holder.retired.setVisibility(item.isRetired ? View.VISIBLE : View.GONE);
holder.alias.setVisibility(item.isAlias ? View.VISIBLE : View.GONE);
return convertView;
}
}
protected static class BeerViewHolder {
TextView beer, overall, count, rated, retired, alias;
}
private class BrewerPagerAdapter extends PagerAdapter {
private View pagerDetailsView;
public BrewerPagerAdapter() {
LayoutInflater inflater = getActivity().getLayoutInflater();
pagerDetailsView = (ScrollView) inflater.inflate(R.layout.fragment_brewerdetails, null);
beersView = (ListView) inflater.inflate(R.layout.fragment_pagerlist, null);
nameText = (TextView) pagerDetailsView.findViewById(R.id.name);
descriptionText = (TextView) pagerDetailsView.findViewById(R.id.description);
locationText = (Button) pagerDetailsView.findViewById(R.id.location);
websiteButton = (Button) pagerDetailsView.findViewById(R.id.website);
facebookButton = (Button) pagerDetailsView.findViewById(R.id.facebook);
twitterButton = (Button) pagerDetailsView.findViewById(R.id.twitter);
setMapView((MapView) pagerDetailsView.findViewById(R.id.map_brewer));
locationText.setOnClickListener(onLocationClick);
websiteButton.setOnClickListener(onWebsiteClick);
facebookButton.setOnClickListener(onFacebookClick);
twitterButton.setOnClickListener(onTwitterClick);
}
@Override
public int getCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getActivity().getString(R.string.app_details).toUpperCase(Locale.getDefault());
case 1:
return getActivity().getString(R.string.brewers_beers).toUpperCase(Locale.getDefault());
}
return null;
}
@Override
public Object instantiateItem(View container, int position) {
switch (position) {
case 0:
((ViewPager) container).addView(pagerDetailsView, 0);
return pagerDetailsView;
case 1:
((ViewPager) container).addView(beersView, 0);
return beersView;
}
return null;
}
@Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == (View) object;
}
}
}