package cgeo.geocaching.filter;
import cgeo.geocaching.R;
import cgeo.geocaching.log.LogEntry;
import cgeo.geocaching.models.Geocache;
import cgeo.geocaching.utils.CalendarUtils;
import cgeo.geocaching.utils.TextUtils;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class StateFilterFactory implements IFilterFactory {
static class StateArchivedFilter extends AbstractFilter {
public static final Creator<StateArchivedFilter> CREATOR
= new Parcelable.Creator<StateArchivedFilter>() {
@Override
public StateArchivedFilter createFromParcel(final Parcel in) {
return new StateArchivedFilter(in);
}
@Override
public StateArchivedFilter[] newArray(final int size) {
return new StateArchivedFilter[size];
}
};
StateArchivedFilter() {
super(R.string.cache_status_archived);
}
protected StateArchivedFilter(final Parcel in) {
super(in);
}
@Override
public boolean accepts(@NonNull final Geocache cache) {
return cache.isArchived();
}
}
static class StateDisabledFilter extends AbstractFilter {
public static final Creator<StateDisabledFilter> CREATOR
= new Parcelable.Creator<StateDisabledFilter>() {
@Override
public StateDisabledFilter createFromParcel(final Parcel in) {
return new StateDisabledFilter(in);
}
@Override
public StateDisabledFilter[] newArray(final int size) {
return new StateDisabledFilter[size];
}
};
StateDisabledFilter() {
super(R.string.cache_status_disabled);
}
protected StateDisabledFilter(final Parcel in) {
super(in);
}
@Override
public boolean accepts(@NonNull final Geocache cache) {
return cache.isDisabled() && !cache.isArchived();
}
}
static class StateFoundFilter extends AbstractFilter {
public static final Creator<StateFoundFilter> CREATOR = new Parcelable.Creator<StateFoundFilter>() {
@Override
public StateFoundFilter createFromParcel(final Parcel in) {
return new StateFoundFilter(in);
}
@Override
public StateFoundFilter[] newArray(final int size) {
return new StateFoundFilter[size];
}
};
StateFoundFilter() {
super(R.string.cache_status_found);
}
protected StateFoundFilter(final Parcel in) {
super(in);
}
@Override
public boolean accepts(@NonNull final Geocache cache) {
return cache.isFound();
}
}
static class StateFoundLastMonthFilter extends AbstractFilter {
private static final double THIRTY_DAYS_MSECS = 30d * 86400d * 1000d;
public static final Creator<StateFoundLastMonthFilter> CREATOR = new Parcelable.Creator<StateFoundLastMonthFilter>() {
@Override
public StateFoundLastMonthFilter createFromParcel(final Parcel in) {
return new StateFoundLastMonthFilter(in);
}
@Override
public StateFoundLastMonthFilter[] newArray(final int size) {
return new StateFoundLastMonthFilter[size];
}
};
private final long today;
StateFoundLastMonthFilter() {
super(R.string.cache_found_last_30_days);
today = Calendar.getInstance().getTimeInMillis();
}
protected StateFoundLastMonthFilter(final Parcel in) {
super(in);
today = Calendar.getInstance().getTimeInMillis();
}
@Override
public boolean accepts(@NonNull final Geocache cache) {
for (final LogEntry log : cache.getLogs()) {
if (log.getType().isFoundLog() && foundLastMonth(log)) {
return true;
}
}
return false;
}
/**
* Inline version of {@link CalendarUtils#daysSince(long) to avoid performance issues} with {@link Calendar}
* instance creation. We totally neglect the time of day correction, since it is acceptable to have an error of
* +/- 1 day with this 30 days filter.
*/
private boolean foundLastMonth(final LogEntry log) {
return today - log.date <= THIRTY_DAYS_MSECS;
}
}
static class StateNeverFoundFilter extends AbstractFilter {
public static final Creator<StateNeverFoundFilter> CREATOR = new Parcelable.Creator<StateNeverFoundFilter>() {
@Override
public StateNeverFoundFilter createFromParcel(final Parcel in) {
return new StateNeverFoundFilter(in);
}
@Override
public StateNeverFoundFilter[] newArray(final int size) {
return new StateNeverFoundFilter[size];
}
};
StateNeverFoundFilter() {
super(R.string.cache_never_found);
}
protected StateNeverFoundFilter(final Parcel in) {
super(in);
}
@Override
public boolean accepts(@NonNull final Geocache cache) {
if (cache.getFindsCount() > 0) {
return false;
}
// find counts don't exist for every connector, so we also check the logs
for (final LogEntry log : cache.getLogs()) {
if (log.getType().isFoundLog()) {
return false;
}
}
return true;
}
}
static class StateNonPremiumFilter extends AbstractFilter {
public static final Creator<StateNonPremiumFilter> CREATOR
= new Parcelable.Creator<StateNonPremiumFilter>() {
@Override
public StateNonPremiumFilter createFromParcel(final Parcel in) {
return new StateNonPremiumFilter(in);
}
@Override
public StateNonPremiumFilter[] newArray(final int size) {
return new StateNonPremiumFilter[size];
}
};
StateNonPremiumFilter() {
super(R.string.cache_status_not_premium);
}
protected StateNonPremiumFilter(final Parcel in) {
super(in);
}
@Override
public boolean accepts(@NonNull final Geocache cache) {
return !cache.isPremiumMembersOnly();
}
}
static class StateNotFoundFilter extends AbstractFilter {
public static final Creator<StateNotFoundFilter> CREATOR = new Parcelable.Creator<StateNotFoundFilter>() {
@Override
public StateNotFoundFilter createFromParcel(final Parcel in) {
return new StateNotFoundFilter(in);
}
@Override
public StateNotFoundFilter[] newArray(final int size) {
return new StateNotFoundFilter[size];
}
};
StateNotFoundFilter() {
super(R.string.cache_not_status_found);
}
protected StateNotFoundFilter(final Parcel in) {
super(in);
}
@Override
public boolean accepts(@NonNull final Geocache cache) {
return !cache.isFound();
}
}
static class StateNotStoredFilter extends AbstractFilter {
public static final Creator<StateNotStoredFilter> CREATOR
= new Parcelable.Creator<StateNotStoredFilter>() {
@Override
public StateNotStoredFilter createFromParcel(final Parcel in) {
return new StateNotStoredFilter(in);
}
@Override
public StateNotStoredFilter[] newArray(final int size) {
return new StateNotStoredFilter[size];
}
};
StateNotStoredFilter() {
super(R.string.cache_status_not_stored);
}
protected StateNotStoredFilter(final Parcel in) {
super(in);
}
@Override
public boolean accepts(@NonNull final Geocache cache) {
return !cache.isOffline();
}
}
static class StatePremiumFilter extends AbstractFilter {
public static final Creator<StatePremiumFilter> CREATOR
= new Parcelable.Creator<StatePremiumFilter>() {
@Override
public StatePremiumFilter createFromParcel(final Parcel in) {
return new StatePremiumFilter(in);
}
@Override
public StatePremiumFilter[] newArray(final int size) {
return new StatePremiumFilter[size];
}
};
StatePremiumFilter() {
super(R.string.cache_status_premium);
}
protected StatePremiumFilter(final Parcel in) {
super(in);
}
@Override
public boolean accepts(@NonNull final Geocache cache) {
return cache.isPremiumMembersOnly();
}
}
static class StateStoredFilter extends AbstractFilter {
public static final Creator<StateStoredFilter> CREATOR
= new Parcelable.Creator<StateStoredFilter>() {
@Override
public StateStoredFilter createFromParcel(final Parcel in) {
return new StateStoredFilter(in);
}
@Override
public StateStoredFilter[] newArray(final int size) {
return new StateStoredFilter[size];
}
};
StateStoredFilter() {
super(R.string.cache_status_stored);
}
protected StateStoredFilter(final Parcel in) {
super(in);
}
@Override
public boolean accepts(@NonNull final Geocache cache) {
return cache.isOffline();
}
}
@Override
@NonNull
public List<IFilter> getFilters() {
final List<IFilter> filters = new ArrayList<>(6);
filters.add(new StateFoundFilter());
filters.add(new StateNotFoundFilter());
filters.add(new StateNeverFoundFilter());
filters.add(new StateFoundLastMonthFilter());
filters.add(new StateArchivedFilter());
filters.add(new StateDisabledFilter());
filters.add(new StatePremiumFilter());
filters.add(new StateNonPremiumFilter());
filters.add(new StateStoredFilter());
filters.add(new StateNotStoredFilter());
filters.add(new RatingFilter());
filters.add(new TrackablesFilter());
filters.add(new MultiListingFilter());
Collections.sort(filters, new Comparator<IFilter>() {
@Override
public int compare(final IFilter filter1, final IFilter filter2) {
return TextUtils.COLLATOR.compare(filter1.getName(), filter2.getName());
}
});
return filters;
}
}