package com.quran.labs.androidquran.widgets;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.annotation.DrawableRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.quran.labs.androidquran.R;
import com.quran.labs.androidquran.common.QariItem;
import com.quran.labs.androidquran.data.Constants;
import com.quran.labs.androidquran.util.AudioUtils;
import com.quran.labs.androidquran.util.QuranScreenInfo;
import com.quran.labs.androidquran.util.QuranSettings;
import com.quran.labs.androidquran.util.QuranUtils;
import java.util.List;
public class AudioStatusBar extends LeftToRightLinearLayout {
public static final int STOPPED_MODE = 1;
public static final int DOWNLOADING_MODE = 2;
public static final int PLAYING_MODE = 3;
public static final int PAUSED_MODE = 4;
public static final int PROMPT_DOWNLOAD_MODE = 5;
private Context context;
private int currentMode;
private int buttonWidth;
private int separatorWidth;
private int separatorSpacing;
private int textFontSize;
private int textFullFontSize;
private int spinnerPadding;
private QariAdapter adapter;
private int currentQari;
private int currentRepeat = 0;
@DrawableRes private int itemBackground;
private boolean isRtl;
private boolean isDualPageMode;
private boolean hasErrorText;
private boolean haveCriticalError = false;
private SharedPreferences sharedPreferences;
private QuranSpinner spinner;
private TextView progressText;
private ProgressBar progressBar;
private RepeatButton repeatButton;
private AudioBarListener audioBarListener;
private int[] repeatValues = {0, 1, 2, 3, -1};
public interface AudioBarListener {
void onPlayPressed();
void onPausePressed();
void onNextPressed();
void onPreviousPressed();
void onStopPressed();
void onCancelPressed(boolean stopDownload);
void setRepeatCount(int repeatCount);
void onAcceptPressed();
void onAudioSettingsPressed();
}
public AudioStatusBar(Context context) {
this(context, null);
}
public AudioStatusBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AudioStatusBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
Resources resources = getResources();
buttonWidth = resources.getDimensionPixelSize(
R.dimen.audiobar_button_width);
separatorWidth = resources.getDimensionPixelSize(
R.dimen.audiobar_separator_width);
separatorSpacing = resources.getDimensionPixelSize(
R.dimen.audiobar_separator_padding);
textFontSize = resources.getDimensionPixelSize(
R.dimen.audiobar_text_font_size);
textFullFontSize = resources.getDimensionPixelSize(
R.dimen.audiobar_text_full_font_size);
spinnerPadding = resources
.getDimensionPixelSize(R.dimen.audiobar_spinner_padding);
setOrientation(LinearLayout.HORIZONTAL);
// only flip the layout when the language is rtl and we're on api 17+
isRtl = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 &&
(QuranSettings.getInstance(this.context).isArabicNames() || QuranUtils.isRtl());
isDualPageMode = QuranScreenInfo.getOrMakeInstance(this.context).isDualPageMode(this.context);
sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context.getApplicationContext());
currentQari = sharedPreferences.getInt(Constants.PREF_DEFAULT_QARI, 0);
itemBackground = 0;
if (attrs != null) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.AudioStatusBar);
itemBackground = ta.getResourceId(R.styleable.AudioStatusBar_android_itemBackground,
itemBackground);
ta.recycle();
}
List<QariItem> qariList = AudioUtils.getQariList(this.context);
// TODO: optimize - PREF_DEFAULT_QARI is the qari id, should introduce a helper pref for pos
final int qaris = qariList.size();
if (currentQari >= qaris || qariList.get(currentQari).getId() != currentQari) {
// figure out the updated position for the index
int updatedIndex = 0;
for (int i = 0; i < qaris; i++) {
if (qariList.get(i).getId() == currentQari) {
updatedIndex = i;
break;
}
}
currentQari = updatedIndex;
}
adapter = new QariAdapter(this.context, qariList,
R.layout.sherlock_spinner_item, R.layout.sherlock_spinner_dropdown_item);
showStoppedMode();
}
public int getCurrentMode() {
return currentMode;
}
public void switchMode(int mode) {
if (mode == currentMode) {
return;
}
if (mode == STOPPED_MODE) {
showStoppedMode();
} else if (mode == PROMPT_DOWNLOAD_MODE) {
showPromptForDownloadMode();
} else if (mode == DOWNLOADING_MODE) {
showDownloadingMode();
} else if (mode == PLAYING_MODE) {
showPlayingMode(false);
} else {
showPlayingMode(true);
}
}
@NonNull
public QariItem getAudioInfo() {
final int position = spinner != null ? spinner.getSelectedItemPosition() : currentQari;
return adapter.getItem(position);
}
public void updateSelectedItem() {
if (spinner != null) {
spinner.setSelection(currentQari);
}
}
public void setProgress(int progress) {
if (hasErrorText) {
progressText.setText(R.string.downloading_title);
hasErrorText = false;
}
if (progressBar != null) {
if (progress >= 0) {
progressBar.setIndeterminate(false);
progressBar.setProgress(progress);
progressBar.setMax(100);
} else {
progressBar.setIndeterminate(true);
}
}
}
public void setProgressText(String progressText, boolean isCriticalError) {
if (this.progressText != null) {
hasErrorText = true;
this.progressText.setText(progressText);
if (isCriticalError && progressBar != null) {
progressBar.setVisibility(View.GONE);
this.progressText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
textFullFontSize);
haveCriticalError = true;
}
}
}
private void showStoppedMode() {
currentMode = STOPPED_MODE;
removeAllViews();
if (isRtl) {
addSpinner();
addSeparator();
addButton(R.drawable.ic_play, false);
} else {
addButton(R.drawable.ic_play, false);
addSeparator();
addSpinner();
}
}
private static class QariAdapter extends BaseAdapter {
@NonNull LayoutInflater mInflater;
@NonNull private final List<QariItem> mItems;
@LayoutRes private final int mLayoutViewId;
@LayoutRes private final int mDropDownViewId;
QariAdapter(@NonNull Context context,
@NonNull List<QariItem> items,
@LayoutRes int layoutViewId,
@LayoutRes int dropDownViewId) {
mItems = items;
mLayoutViewId = layoutViewId;
mDropDownViewId = dropDownViewId;
mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return mItems.size();
}
@Override
public QariItem getItem(int position) {
return mItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getViewInternal(position, convertView, parent, mLayoutViewId);
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getViewInternal(position, convertView, parent, mDropDownViewId);
}
private View getViewInternal(int position, View convertView,
ViewGroup parent, @LayoutRes int resource) {
TextView textView;
if (convertView == null) {
textView = (TextView) mInflater.inflate(resource, parent, false);
} else {
textView = (TextView) convertView;
}
QariItem item = getItem(position);
textView.setText(item.getName());
return textView;
}
}
private void addSpinner() {
if (spinner == null) {
spinner = new QuranSpinner(context, null,
R.attr.actionDropDownStyle);
spinner.setDropDownVerticalOffset(spinnerPadding);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(
new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position != currentQari) {
sharedPreferences.edit().
putInt(Constants.PREF_DEFAULT_QARI, adapter.getItem(position).getId()).apply();
currentQari = position;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
spinner.setSelection(currentQari);
final LayoutParams params = new LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT);
params.weight = 1;
if (isRtl) {
ViewCompat.setLayoutDirection(spinner, ViewCompat.LAYOUT_DIRECTION_RTL);
params.leftMargin = spinnerPadding;
} else {
params.rightMargin = spinnerPadding;
}
addView(spinner, params);
}
private void showPromptForDownloadMode() {
currentMode = PROMPT_DOWNLOAD_MODE;
removeAllViews();
if (isRtl) {
addButton(R.drawable.ic_cancel, false);
addDownloadOver3gPrompt();
addSeparator();
addButton(R.drawable.ic_accept, false);
} else {
addButton(R.drawable.ic_accept, false);
addSeparator();
addDownloadOver3gPrompt();
addButton(R.drawable.ic_cancel, false);
}
}
private void addDownloadOver3gPrompt() {
TextView mPromptText = new TextView(context);
mPromptText.setTextColor(Color.WHITE);
mPromptText.setGravity(Gravity.CENTER_VERTICAL);
mPromptText.setTextSize(TypedValue.COMPLEX_UNIT_PX,
textFontSize);
mPromptText.setText(R.string.download_non_wifi_prompt);
LayoutParams params = new LayoutParams(0,
LayoutParams.MATCH_PARENT);
params.weight = 1;
addView(mPromptText, params);
}
private void showDownloadingMode() {
currentMode = DOWNLOADING_MODE;
removeAllViews();
if (isRtl) {
addDownloadProgress();
addSeparator();
addButton(R.drawable.ic_cancel, false);
} else {
addButton(R.drawable.ic_cancel, false);
addSeparator();
addDownloadProgress();
}
}
private void addDownloadProgress() {
LinearLayout ll = new LinearLayout(context);
ll.setOrientation(LinearLayout.VERTICAL);
progressBar = (ProgressBar) LayoutInflater.from(context)
.inflate(R.layout.download_progress_bar, this, false);
progressBar.setIndeterminate(true);
progressBar.setVisibility(View.VISIBLE);
ll.addView(progressBar, LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
progressText = new TextView(context);
progressText.setTextColor(Color.WHITE);
progressText.setGravity(Gravity.CENTER_VERTICAL);
progressText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textFontSize);
progressText.setText(R.string.downloading_title);
ll.addView(progressText, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
LinearLayout.LayoutParams lp =
new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT);
lp.weight = 1;
lp.setMargins(separatorSpacing, 0, separatorSpacing, 0);
if (isRtl) {
lp.leftMargin = spinnerPadding;
} else {
lp.rightMargin = spinnerPadding;
}
addView(ll, lp);
}
private void showPlayingMode(boolean isPaused) {
removeAllViews();
final boolean withWeight = !isDualPageMode;
int button;
if (isPaused) {
button = R.drawable.ic_play;
currentMode = PAUSED_MODE;
} else {
button = R.drawable.ic_pause;
currentMode = PLAYING_MODE;
}
addButton(R.drawable.ic_stop, withWeight);
addButton(R.drawable.ic_previous, withWeight);
addButton(button, withWeight);
addButton(R.drawable.ic_next, withWeight);
repeatButton = new RepeatButton(context);
addButton(repeatButton, R.drawable.ic_repeat, withWeight);
updateRepeatButtonText();
addButton(R.drawable.ic_action_settings, withWeight);
}
private void addButton(int imageId, boolean withWeight) {
addButton(new ImageView(context), imageId, withWeight);
}
private void addButton(@NonNull ImageView button, int imageId, boolean withWeight) {
button.setImageResource(imageId);
button.setScaleType(ImageView.ScaleType.CENTER);
button.setOnClickListener(mOnClickListener);
button.setTag(imageId);
button.setBackgroundResource(itemBackground);
final LayoutParams params = new LayoutParams(
withWeight ? 0 : buttonWidth, LayoutParams.MATCH_PARENT);
if (withWeight) {
params.weight = 1;
}
addView(button, params);
}
private void addSeparator() {
ImageView separator = new ImageView(context);
separator.setBackgroundColor(Color.WHITE);
separator.setPadding(0, separatorSpacing, 0, separatorSpacing);
LinearLayout.LayoutParams paddingParams =
new LayoutParams(separatorWidth, LayoutParams.MATCH_PARENT);
final int right = isRtl ? 0 : separatorSpacing;
final int left = isRtl ? separatorSpacing : 0;
paddingParams.setMargins(left, 0, right, 0);
addView(separator, paddingParams);
}
private void incrementRepeat() {
currentRepeat++;
if (currentRepeat == repeatValues.length) {
currentRepeat = 0;
}
updateRepeatButtonText();
}
private void updateRepeatButtonText() {
String str;
int value = repeatValues[currentRepeat];
if (value == 0) {
str = "";
} else if (value > 0) {
str = repeatValues[currentRepeat] + "";
} else {
str = context.getString(R.string.infinity);
}
repeatButton.setText(str);
}
public void setRepeatCount(int repeatCount) {
boolean updated = false;
for (int i = 0; i < repeatValues.length; i++) {
if (repeatValues[i] == repeatCount) {
if (currentRepeat != i) {
currentRepeat = i;
updated = true;
}
break;
}
}
if (updated && repeatButton != null) {
updateRepeatButtonText();
}
}
public void setAudioBarListener(AudioBarListener listener) {
audioBarListener = listener;
}
OnClickListener mOnClickListener = new OnClickListener() {
@Override
public void onClick(View view) {
if (audioBarListener != null) {
int tag = (Integer) view.getTag();
switch (tag) {
case R.drawable.ic_play:
audioBarListener.onPlayPressed();
break;
case R.drawable.ic_stop:
audioBarListener.onStopPressed();
break;
case R.drawable.ic_pause:
audioBarListener.onPausePressed();
break;
case R.drawable.ic_next:
audioBarListener.onNextPressed();
break;
case R.drawable.ic_previous:
audioBarListener.onPreviousPressed();
break;
case R.drawable.ic_repeat:
incrementRepeat();
audioBarListener.setRepeatCount(repeatValues[currentRepeat]);
break;
case R.drawable.ic_cancel:
if (haveCriticalError) {
haveCriticalError = false;
switchMode(STOPPED_MODE);
} else {
audioBarListener.onCancelPressed(currentMode != PROMPT_DOWNLOAD_MODE);
}
break;
case R.drawable.ic_accept:
audioBarListener.onAcceptPressed();
break;
case R.drawable.ic_action_settings:
audioBarListener.onAudioSettingsPressed();
break;
}
}
}
};
}