package com.thebluealliance.androidclient.binders;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.thebluealliance.androidclient.R;
import com.thebluealliance.androidclient.TbaLogger;
import com.thebluealliance.androidclient.eventbus.ActionBarTitleEvent;
import com.thebluealliance.androidclient.eventbus.EventRankingsEvent;
import com.thebluealliance.androidclient.eventbus.EventStatsEvent;
import com.thebluealliance.androidclient.eventbus.LiveEventMatchUpdateEvent;
import com.thebluealliance.androidclient.helpers.WebcastHelper;
import com.thebluealliance.androidclient.listeners.EventInfoContainerClickListener;
import com.thebluealliance.androidclient.listeners.SocialClickListener;
import com.thebluealliance.androidclient.listeners.WebcastClickListener;
import com.thebluealliance.androidclient.listitems.MatchListElement;
import com.thebluealliance.androidclient.renderers.MatchRenderer;
import com.thebluealliance.androidclient.types.WebcastType;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.CardView;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import javax.annotation.Nullable;
import javax.inject.Inject;
import butterknife.Bind;
import butterknife.ButterKnife;
import rx.android.schedulers.AndroidSchedulers;
import static com.thebluealliance.androidclient.renderers.MatchRenderer.RENDER_DEFAULT;
public class EventInfoBinder extends AbstractDataBinder<EventInfoBinder.Model> {
private LayoutInflater mInflater;
private MatchRenderer mMatchRenderer;
private boolean mIsLive;
private boolean mAreViewsBound;
@Inject SocialClickListener mSocialClickListener;
@Inject EventInfoContainerClickListener mInfoClickListener;
@Bind(R.id.content) View content;
@Bind(R.id.event_name) TextView eventName;
@Bind(R.id.event_date) TextView eventDate;
@Bind(R.id.event_venue) TextView eventVenue;
@Bind(R.id.top_teams) TextView topTeams;
@Bind(R.id.top_oprs) TextView topOprs;
@Bind(R.id.top_teams_container) View topTeamsContainer;
@Bind(R.id.top_oprs_container) View topOprsContainer;
@Bind(R.id.progress) ProgressBar progressBar;
@Bind(R.id.event_date_container) View eventDateContainer;
@Bind(R.id.event_venue_container) View eventVenueContainer;
@Bind(R.id.event_website_container) View eventWebsiteContainer;
@Bind(R.id.event_website_title) TextView eventWebsiteTitle;
@Bind(R.id.event_twitter_container) View eventTwitterContainer;
@Bind(R.id.event_twitter_title) TextView eventTwitterTitle;
@Bind(R.id.event_youtube_container) View eventYoutubeContainer;
@Bind(R.id.event_youtube_title) TextView eventYoutubeTitle;
@Bind(R.id.event_cd_container) View eventCdContainer;
@Bind(R.id.last_match_view) FrameLayout lastMatchView;
@Bind(R.id.next_match_container) CardView nextMatchContainer;
@Bind(R.id.next_match_view) FrameLayout nextMatchView;
@Bind(R.id.last_match_container) CardView lastMatchContainer;
@Bind(R.id.event_webcast_container) FrameLayout webcastContainer;
@Bind((R.id.event_webcast_button)) Button webcastButton;
@Inject
public EventInfoBinder(MatchRenderer renderer,
SocialClickListener socialClickListener,
EventInfoContainerClickListener eventInfoContainerClickListener) {
mSocialClickListener = socialClickListener;
mInfoClickListener = eventInfoContainerClickListener;
mMatchRenderer = renderer;
mIsLive = false;
mAreViewsBound = false;
}
public void setInflater(LayoutInflater inflater) {
mInflater = inflater;
}
@Override
public void bindViews() {
if (!mAreViewsBound) {
ButterKnife.bind(this, mRootView);
mAreViewsBound = true;
}
}
@Override
public void updateData(@Nullable Model data) {
if (data == null) {
if (!isDataBound()) {
bindNoDataView();
}
return;
}
mSocialClickListener.setModelKey(data.eventKey);
mIsLive = data.isLive;
eventName.setText(data.nameString);
if (data.dateString == null || data.dateString.isEmpty()) {
eventDateContainer.setVisibility(View.GONE);
} else {
eventDate.setText(data.dateString);
}
// Show a venue if it is available, otherwise show just the location. If neither is available, hide
if (data.venueString != null && !data.venueString.isEmpty()) {
eventVenue.setText(data.venueString);
} else if (data.locationString != null && !data.locationString.isEmpty()) {
eventVenue.setText(data.locationString);
} else {
eventVenue.setText(R.string.no_location_available);
eventVenueContainer.setVisibility(View.GONE);
}
// setup social media intents
// Default to showing the nav arrow in the venue view and the venue view being clickable
// We need to set these again even though they're defined in XML in case we gain a location
// or venue on a refresh and we're reusing the same view.
eventVenueContainer.setFocusable(true);
eventVenueContainer.setClickable(true);
eventVenueContainer.setOnClickListener(mSocialClickListener);
if (data.venueString != null && !data.venueString.isEmpty()) {
// Set the tag to the event venue if it is available
eventVenueContainer.setTag("geo:0,0?q=" + Uri.encode(data.venueString));
} else if (data.locationString != null && !data.locationString.isEmpty()) {
// Otherwise, use the location
eventVenueContainer.setTag("geo:0,0?q=" + Uri.encode(data.locationString));
} else {
// If neither location nor venue are available, hide the nav arrow, remove the tag,
// and set the view to not clickable so the user cannot interact with it.
// It will contain the text "No location available".
eventVenueContainer.setTag(null);
eventVenueContainer.setFocusable(false);
eventVenueContainer.setClickable(false);
}
// If the event doesn't have a defined website, create a Google search for the event name
if (data.eventWebsite != null && data.eventWebsite.isEmpty()) {
eventWebsiteContainer.setTag("https://www.google.com/search?q=" + Uri.encode(data.nameString));
eventWebsiteTitle.setText(R.string.find_event_on_google);
} else {
eventWebsiteContainer.setTag(data.eventWebsite);
eventWebsiteTitle.setText(R.string.view_event_website);
}
eventWebsiteContainer.setOnClickListener(mSocialClickListener);
eventTwitterContainer.setTag("https://twitter.com/search?q=%23" + data.eventKey);
eventTwitterTitle.setText(mActivity.getString(R.string.view_event_twitter, data.eventKey));
eventTwitterContainer.setOnClickListener(mSocialClickListener);
eventYoutubeContainer.setTag("https://www.youtube.com/results?search_query=" + data.eventKey);
eventYoutubeTitle.setText(mActivity.getString(R.string.view_event_youtube, data.eventKey));
eventYoutubeContainer.setOnClickListener(mSocialClickListener);
eventCdContainer.setTag("http://www.chiefdelphi.com/media/photos/tags/" + data.eventKey);
eventCdContainer.setOnClickListener(mSocialClickListener);
if (data.isLive && data.webcasts != null && data.webcasts.size() > 0) {
if (data.webcasts.size() == 1) {
// Only one webcast, we can link directly to that
JsonObject eventWebcast = data.webcasts.get(0).getAsJsonObject();
WebcastType webcastType = WebcastHelper.getType(eventWebcast.get("type")
.getAsString());
webcastButton.setText(webcastType.render(mActivity));
webcastButton.setOnClickListener(new WebcastClickListener(mActivity, data.eventKey,
webcastType, eventWebcast, 1));
} else {
webcastButton.setText(R.string.view_webcast_button);
webcastButton.setOnClickListener(v -> {
Dialog chooserDialog = buildMultiWebcastDialog(data.webcasts, data.eventKey);
chooserDialog.show();
});
}
webcastContainer.setVisibility(View.VISIBLE);
}
content.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
EventBus.getDefault().post(new ActionBarTitleEvent(data.actionBarTitle, data.actionBarSubtitle));
mNoDataBinder.unbindData();
setDataBound(true);
}
@Override
public void onComplete() {
if (progressBar != null) {
progressBar.setVisibility(View.GONE);
}
if (!isDataBound()) {
bindNoDataView();
}
}
@Override
public void onError(Throwable throwable) {
TbaLogger.e(TbaLogger.getStackTraceString(throwable));
// If we received valid data from the cache but get an error from the network operations,
// don't display the "No data" message.
if (!isDataBound()) {
bindNoDataView();
}
}
@Override
public void unbind(boolean unbindViews) {
super.unbind(unbindViews);
if (unbindViews) {
ButterKnife.unbind(this);
mAreViewsBound = false;
}
}
private void bindNoDataView() {
try {
content.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
mNoDataBinder.bindData(mNoDataParams);
} catch (Exception e) {
e.printStackTrace();
}
}
public static class Model {
public String eventKey;
public String actionBarTitle;
public String actionBarSubtitle;
public String nameString;
public String dateString;
public String venueString;
public String locationString;
public String eventWebsite;
public boolean isLive;
public JsonArray webcasts;
}
protected void showLastMatch(MatchListElement match) {
if (!mAreViewsBound) {
bindViews();
}
lastMatchView.setVisibility(View.VISIBLE);
lastMatchContainer.setVisibility(View.VISIBLE);
lastMatchView.removeAllViews();
lastMatchView.addView(match.getView(mActivity, mInflater, null));
}
protected void showNextMatch(MatchListElement match) {
if (!mAreViewsBound) {
bindViews();
}
nextMatchView.setVisibility(View.VISIBLE);
nextMatchContainer.setVisibility(View.VISIBLE);
nextMatchView.removeAllViews();
nextMatchView.addView(match.getView(mActivity, mInflater, null));
}
protected void hideLastMatch() {
if (!mAreViewsBound) {
bindViews();
}
lastMatchContainer.setVisibility(View.GONE);
}
protected void hideNextMatch() {
if (!mAreViewsBound) {
bindViews();
}
nextMatchContainer.setVisibility(View.GONE);
}
@SuppressWarnings("unused")
@Subscribe
public void onLiveEventMatchesUpdated(LiveEventMatchUpdateEvent event) {
AndroidSchedulers.mainThread().createWorker().schedule(() -> {
if (mIsLive && event != null && event.getLastMatch() != null) {
TbaLogger.d("showing last match");
showLastMatch(mMatchRenderer.renderFromModel(event.getLastMatch(), RENDER_DEFAULT));
} else {
TbaLogger.d("hiding last match");
hideLastMatch();
}
if (mIsLive && event != null && event.getNextMatch() != null) {
TbaLogger.d("showing next match");
showNextMatch(mMatchRenderer.renderFromModel(event.getNextMatch(), RENDER_DEFAULT));
} else {
TbaLogger.d("hiding next match");
hideNextMatch();
}
});
}
@SuppressWarnings("unused")
@Subscribe
public void onEventRankingsUpdated(EventRankingsEvent event) {
AndroidSchedulers.mainThread().createWorker().schedule(() -> {
if (topTeamsContainer == null || topTeams == null) {
return;
}
topTeamsContainer.setVisibility(View.VISIBLE);
topTeamsContainer.setOnClickListener(mInfoClickListener);
topTeams.setText(Html.fromHtml(event.getRankString()));
});
}
@SuppressWarnings("unused")
@Subscribe
public void onEventStatsUpdated(EventStatsEvent event) {
AndroidSchedulers.mainThread().createWorker().schedule(() -> {
if (topOprsContainer == null || topOprs == null) {
return;
}
topOprsContainer.setVisibility(View.VISIBLE);
topOprsContainer.setOnClickListener(mInfoClickListener);
topOprs.setText(Html.fromHtml(event.getStatString()));
});
}
private Dialog buildMultiWebcastDialog(final JsonArray webcasts, final String eventKey) {
String[] choices = new String[webcasts.size()];
for (int i = 0; i < webcasts.size(); i++) {
JsonObject webcastDetails = webcasts.get(i).getAsJsonObject();
WebcastType webcastType = WebcastHelper.getType(webcastDetails.get("type")
.getAsString());
choices[i] = mActivity.getString(R.string.select_multi_webcast_stream_format, i + 1,
webcastType.render(mActivity));
}
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
builder.setTitle(R.string.select_multi_webcast)
.setItems(choices, (dialog, which) -> {
JsonObject details = webcasts.get(which).getAsJsonObject();
WebcastType type = WebcastHelper.getType(details.get("type").getAsString());
Intent intent = WebcastHelper.getIntentForWebcast(mActivity, eventKey, type,
details, which + 1);
try {
mActivity.startActivity(intent);
dialog.dismiss();
} catch (ActivityNotFoundException ex) {
// Unable to find an activity to handle the webcast
// Fall back by just opening Gameday in browser
String url = mActivity.getString(R.string.webcast_gameday_pattern,
eventKey, which + 1);
Intent gamedayIntent = WebcastHelper.getWebIntentForUrl(url);
mActivity.startActivity(gamedayIntent);
dialog.dismiss();
}
});
return builder.create();
}
}