public class SharedPreferencesHelper {

    private static final String KEY_IMAGE_UPLOADING = "image_uploading_";
    private final SharedPreferences mSharedPreferences;

    public SharedPreferencesHelper(SharedPreferences sharedPreferences) {
        mSharedPreferences = sharedPreferences;
    }

    public boolean saveSortBy(int sortBy) {
        SharedPreferences.Editor editor = mSharedPreferences.edit();
        editor.putInt(STATE_CURRENT_SORT, sortBy);
        return editor.commit();
    }

    public int getSortBy() {
        return mSharedPreferences.getInt(STATE_CURRENT_SORT, SORT_BY_EXPIRY);
    }

    public boolean imageUploading(String itemId) {
        return mSharedPreferences.getBoolean(KEY_IMAGE_UPLOADING + itemId, false);
    }

    public void setImageUploading(String itemId) {
        SharedPreferences.Editor editor = mSharedPreferences.edit();
        editor.putBoolean(KEY_IMAGE_UPLOADING + itemId, true);
        editor.apply();
    }

    public void removeImageUploading(String itemId) {
        SharedPreferences.Editor editor = mSharedPreferences.edit();
        editor.remove(KEY_IMAGE_UPLOADING + itemId);
        editor.apply();
    }
} public class AuthActivity extends AppCompatActivity {

    @BindView(R.id.toolbar)
    Toolbar mToolbar;
    @BindView(R.id.appbar_title)
    TextView mAppbarTitle;

    @Override
    public void onBackPressed() {
        setResult(RESULT_CANCELED);
        super.onBackPressed();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_auth);
        ButterKnife.bind(this);
        setSupportActionBar(mToolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayShowTitleEnabled(false);
        }
        Typeface appbarTitle = Typeface.createFromAsset(getAssets(), "Nosifer-Regular.ttf");
        mAppbarTitle.setTypeface(appbarTitle);

        // Create the View
        AuthFragment authFragment = (AuthFragment) getSupportFragmentManager()
                .findFragmentById(R.id.contentFrame);
        if (authFragment == null) {
            authFragment = AuthFragment.newInstance();
            initFragment(authFragment);
        }

        // Create the Presenter which does the following:
        // Sets authFragment as the View for authPresenter.
        // Sets authPresenter as the presenter for authFragment.
        AuthComponent authComponent = DaggerAuthComponent.builder()
                .authModule(new AuthModule(authFragment))
                .applicationComponent(((ItemReaperApplication)getApplication()).getApplicationComponent())
                .build();
        authComponent.getAuthPresenter();
    }

    private void initFragment(Fragment authFragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.contentFrame, authFragment);
        transaction.commit();
    }

    @VisibleForTesting
    public IdlingResource getCountingIdlingResource() {
        return EspressoIdlingResource.getIdlingResource();
    }
} public class Item implements Serializable, Comparable {

    @NonNull
    private String mId = "-1";
    private long mPurchaseDate;
    private int mPricePaid;
    private int mDiscount;
    private long mExpiry;
    @Nullable
    private String mCategory;
    @Nullable
    private String mSubCategory;
    @Nullable
    private String mType;
    @Nullable
    private String mSubType;
    @Nullable
    private String mSubType2;
    @Nullable
    private String mSubType3;
    @Nullable
    private String mMainColour;
    @Nullable
    private String mMainColourShade;
    @Nullable
    private String mAccentColour;
    @Nullable
    private String mSize;
    @Nullable
    private String mBrand;
    @Nullable
    private String mShop;
    @Nullable
    private String mDescription;
    @Nullable
    private String mNote;
    @Nullable
    private String mImageUrl;
    private boolean mDeceased;

    public Item() {
        // Firebase required no arg constructor.
    }

    public Item(@NonNull String id) {
        mId = id;
        mDeceased = false;
    }

    public Item(@NonNull String id, long purchaseDate, int pricePaid, int discount,
                long expiry, @Nullable String category, @Nullable String subCategory,
                @NonNull String type, @Nullable String subType, @Nullable String subType2,
                @Nullable String subType3, @Nullable String mainColour,
                @Nullable String mainColourShade, @Nullable String accentColour,
                @Nullable String size, @Nullable String brand, @Nullable String shop,
                @Nullable String description, @Nullable String note,
                @Nullable String imageUrl, boolean deceased) {
        mId = id;
        mPurchaseDate = purchaseDate;
        mPricePaid = pricePaid;
        mDiscount = discount;
        mExpiry = expiry;
        mCategory = category;
        mSubCategory = subCategory;
        mType = type;
        mSubType = subType;
        mSubType2 = subType2;
        mSubType3 = subType3;
        mMainColour = mainColour;
        mMainColourShade = mainColourShade;
        mAccentColour = accentColour;
        mSize = size;
        mBrand = brand;
        mShop = shop;
        mDescription = description;
        mNote = note;
        mImageUrl = imageUrl;
        mDeceased = deceased;
    }

    @NonNull
    public String getId() {
        return mId;
    }

    public void setId(@NonNull String id) {
        mId = id;
    }

    public long getPurchaseDate() {
        return mPurchaseDate;
    }

    public void setPurchaseDate(long purchaseDate) {
        mPurchaseDate = purchaseDate;
    }

    public int getPricePaid() {
        return mPricePaid;
    }

    public void setPricePaid(int pricePaid) {
        mPricePaid = pricePaid;
    }

    public int getDiscount() {
        return mDiscount;
    }

    public void setDiscount(int discount) {
        mDiscount = discount;
    }

    public long getExpiry() {
        return mExpiry;
    }

    public void setExpiry(long expiry) {
        mExpiry = expiry;
    }

    @Nullable
    public String getCategory() {
        return mCategory;
    }

    public void setCategory(@Nullable String category) {
        mCategory = category;
    }

    @Nullable
    public String getSubCategory() {
        return mSubCategory;
    }

    public void setSubCategory(@Nullable String subCategory) {
        mSubCategory = subCategory;
    }

    @Nullable
    public String getType() {
        return mType;
    }

    public void setType(@Nullable String type) {
        mType = type;
    }

    @Nullable
    public String getSubType() {
        return mSubType;
    }

    public void setSubType(@Nullable String subType) {
        mSubType = subType;
    }

    @Nullable
    public String getSubType2() {
        return mSubType2;
    }

    public void setSubType2(@Nullable String subType2) {
        mSubType2 = subType2;
    }

    @Nullable
    public String getSubType3() {
        return mSubType3;
    }

    public void setSubType3(@Nullable String subType3) {
        mSubType3 = subType3;
    }

    @Nullable
    public String getMainColour() {
        return mMainColour;
    }

    public void setMainColour(@Nullable String mainColour) {
        mMainColour = mainColour;
    }

    @Nullable
    public String getMainColourShade() {
        return mMainColourShade;
    }

    public void setMainColourShade(@Nullable String mainColourShade) {
        mMainColourShade = mainColourShade;
    }

    @Nullable
    public String getAccentColour() {
        return mAccentColour;
    }

    public void setAccentColour(@Nullable String accentColour) {
        mAccentColour = accentColour;
    }

    @Nullable
    public String getSize() {
        return mSize;
    }

    public void setSize(@Nullable String size) {
        mSize = size;
    }

    @Nullable
    public String getBrand() {
        return mBrand;
    }

    public void setBrand(@Nullable String brand) {
        mBrand = brand;
    }

    @Nullable
    public String getShop() {
        return mShop;
    }

    public void setShop(@Nullable String shop) {
        mShop = shop;
    }

    @Nullable
    public String getDescription() {
        return mDescription;
    }

    public void setDescription(@Nullable String description) {
        mDescription = description;
    }

    @Nullable
    public String getNote() {
        return mNote;
    }

    public void setNote(@Nullable String note) {
        mNote = note;
    }

    @Nullable
    public String getImageUrl() {
        return mImageUrl;
    }

    public void setImageUrl(@Nullable String imageUrl) {
        mImageUrl = imageUrl;
    }

    public boolean getDeceased() {
        return mDeceased;
    }

    public void setDeceased(boolean deceased) {
        mDeceased = deceased;
    }

    // For Firebase map
    public Map<String, Object> toMap() {
        Map<String, Object> result = new HashMap<>();
        result.put("id", mId);
        result.put("purchaseDate", mPurchaseDate);
        result.put("pricePaid", mPricePaid);
        result.put("discount", mDiscount);
        result.put("expiry", mExpiry);
        result.put("category", mCategory);
        result.put("subCategory", mSubCategory);
        result.put("type", mType);
        result.put("subType", mSubType);
        result.put("subType2", mSubType2);
        result.put("subType3", mSubType3);
        result.put("mainColour", mMainColour);
        result.put("mainColourShade", mMainColourShade);
        result.put("accentColour", mAccentColour);
        result.put("size", mSize);
        result.put("brand", mBrand);
        result.put("shop", mShop);
        result.put("description", mDescription);
        result.put("note", mNote);
        result.put("imageUrl", mImageUrl);
        result.put("deceased", mDeceased);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof Item && ((Item) obj).getId().equals(mId);
    }

    @Override
    public int hashCode() {
        return mId.hashCode();
    }

    public boolean equalsAllFields(Object obj) {
        boolean result = false;
        if (obj instanceof Item) {
            Item item = (Item) obj;
            result = mId.equals(item.mId) && mPurchaseDate == item.mPurchaseDate
                    && mPricePaid == item.mPricePaid && mDiscount == item.mDiscount
                    && mExpiry == item.mExpiry
                    && (mCategory != null && mCategory.equals(item.mCategory))
                    && (mSubCategory != null && mSubCategory.equals(item.mSubCategory))
                    && (mType != null && mType.equals(item.mType))
                    && (mSubType != null && mSubType.equals(item.mSubType))
                    && (mSubType2 != null && mSubType2.equals(item.mSubType2))
                    && (mSubType3 != null && mSubType3.equals(item.mSubType3))
                    && (mMainColour != null && mMainColour.equals(item.mMainColour))
                    && (mMainColourShade != null && mMainColourShade.equals(item.mMainColourShade))
                    && (mAccentColour != null && mAccentColour.equals(item.mAccentColour))
                    && (mSize != null && mSize.equals(item.mSize))
                    && (mBrand != null && mBrand.equals(item.mBrand))
                    && (mShop != null && mShop.equals(item.mShop))
                    && (mDescription != null && mDescription.equals(item.mDescription))
                    && (mNote != null && mNote.equals(item.mNote))
                    && (mImageUrl != null && mImageUrl.equals(item.mImageUrl))
                    && mDeceased == item.mDeceased;
        }
        return result;
    }

    @Override
    public int compareTo(@NonNull Object item2) {
        if (mExpiry > ((Item) item2).getExpiry()) {
            return 1;
        } else if (mExpiry == ((Item) item2).getExpiry()) {
            return 0;
        } else {
            return -1;
        }
    }
} public class SettingsActivity extends AppCompatActivity {

    @BindView(R.id.toolbar)
    Toolbar mToolbar;
    @BindView(R.id.appbar_title)
    TextView mAppbarTitle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);
        ButterKnife.bind(this);
        setSupportActionBar(mToolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setDisplayShowTitleEnabled(false);
        }
        Typeface appbarTitle = Typeface.createFromAsset(getAssets(), "Nosifer-Regular.ttf");
        mAppbarTitle.setTypeface(appbarTitle);

        getFragmentManager().beginTransaction()
                .replace(R.id.contentFrame, new SettingsFragment())
                .commit();
    }
} public class Analytics {

    private static final String LOGOUT = "logout";

    private static final String PURCHASE_DATE = "purchase_date";
    private static final String PRICE_PAID = "price_paid";
    private static final String DISCOUNT = "discount";
    private static final String EXPIRY = "expiry";
    private static final String CATEGORY = "category";
    private static final String SUB_CATEGORY = "sub_category";
    private static final String TYPE = "type";
    private static final String SUB_TYPE = "sub_type";
    private static final String SUB_TYPE2 = "sub_type2";
    private static final String SUB_TYPE3 = "sub_type3";
    private static final String MAIN_COLOUR = "main_colour";
    private static final String MAIN_COLOUR_SHADE = "main_colour_shade";
    private static final String ACCENT_COLOUR = "accent_colour";
    private static final String SIZE = "size";
    private static final String BRAND = "brand";
    private static final String SHOP = "shop";
    private static final String DESCRIPTION = "description";
    private static final String NOTE = "note";
    private static final String DECEASED = "deceased";
    private static final String VIEW_ABOUT_PAGE = "view_about_page";
    private static final String VIEW_PRIVACY_POLICY = "view_privacy_policy";
    private static final String VIEW_REAPER_ICON_ATTRIBUTION = "view_reaper_icon_attribution";
    private static final String VIEW_REAPER_SOUND_ATTRIBUTION = "view_reaper_sound_attribution";
    private static final String EXPIRE_LIST_ITEM = "expire_list_item";
    private static final String UNDO_EXPIRE_LIST_ITEM = "undo_expire_list_item";
    private static final String ADD_ITEM = "add_item";
    private static final String EXPIRE_ITEM = "expire_item";
    private static final String UNDO_EXPIRE_ITEM = "undo_expire_item";
    private static final String EDIT_ITEM = "edit_item";
    private static final String TAKE_ITEM_PHOTO = "take_item_photo";
    private static final String SELECT_ITEM_IMAGE = "select_item_image";
    private static final String REMOVE_ITEM_IMAGE = "remove_item_image";
    private static final String DELETE_ITEM = "delete_item";
    private static final String UNDO_DELETE_ITEM = "undo_delete_item";
    private static final String SORT_EXPIRED = "sort_expired";
    private static final String SORT_PURCHASE_DATE = "sort_purchase_date";

    public static void logEventLogout(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(LOGOUT, null);
    }

    public static void logEventViewItemList(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(FirebaseAnalytics.Event.VIEW_ITEM_LIST, null);
    }

    public static void logEventViewAboutPage(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(VIEW_ABOUT_PAGE, null);
    }

    public static void logEventViewPrivacyPolicy(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(VIEW_PRIVACY_POLICY, null);
    }

    public static void logEventViewReaperIconAttribution(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(VIEW_REAPER_ICON_ATTRIBUTION, null);
    }

    public static void logEventViewReaperSoundAttribution(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(VIEW_REAPER_SOUND_ATTRIBUTION, null);
    }

    public static void logEventViewSearchResults(Context context, String searchTerm) {
        Bundle params = new Bundle();
        params.putString(FirebaseAnalytics.Param.SEARCH_TERM, searchTerm);
        FirebaseAnalytics.getInstance(context).logEvent(FirebaseAnalytics.Event.VIEW_SEARCH_RESULTS, params);
    }

    public static void logEventExpireListItem(Context context, Item item) {
        Bundle params = new Bundle();
        if (item.getPurchaseDate() != -1) {
            params.putLong(PURCHASE_DATE, item.getPurchaseDate());
        }
        if (item.getPricePaid() != -1) {
            params.putInt(PRICE_PAID, item.getPricePaid());
        }
        if (item.getDiscount() != -1) {
            params.putInt(DISCOUNT, item.getDiscount());
        }
        if (item.getExpiry() != -1) {
            params.putLong(EXPIRY, item.getExpiry());
        }
        if (item.getCategory() != null) {
            params.putString(CATEGORY, item.getCategory());
        }
        if (item.getSubCategory() != null) {
            params.putString(SUB_CATEGORY, item.getSubCategory());
        }
        if (item.getType() != null) {
            params.putString(TYPE, item.getType());
        }
        if (item.getSubType() != null) {
            params.putString(SUB_TYPE, item.getSubType());
        }
        if (item.getSubType2() != null) {
            params.putString(SUB_TYPE2, item.getSubType2());
        }
        if (item.getSubType3() != null) {
            params.putString(SUB_TYPE3, item.getSubType3());
        }
        if (item.getMainColour() != null) {
            params.putString(MAIN_COLOUR, item.getMainColour());
        }
        if (item.getMainColourShade() != null) {
            params.putString(MAIN_COLOUR_SHADE, item.getMainColourShade());
        }
        if (item.getAccentColour() != null) {
            params.putString(ACCENT_COLOUR, item.getAccentColour());
        }
        if (item.getSize() != null) {
            params.putString(SIZE, item.getSize());
        }
        if (item.getBrand() != null) {
            params.putString(BRAND, item.getBrand());
        }
        if (item.getShop() != null) {
            params.putString(SHOP, item.getShop());
        }
        if (item.getDescription() != null) {
            params.putString(DESCRIPTION, item.getDescription());
        }
        if (item.getNote() != null) {
            params.putString(NOTE, item.getNote());
        }
        params.putBoolean(DECEASED, item.getDeceased());
        FirebaseAnalytics.getInstance(context).logEvent(EXPIRE_LIST_ITEM, params);
    }

    public static void logEventUndoExpireListItem(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(UNDO_EXPIRE_LIST_ITEM, null);
    }

    public static void logEventAddItem(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(ADD_ITEM, null);
    }

    public static void logEventViewItem(Context context, Item item) {
        Bundle params = new Bundle();
        if (item.getPurchaseDate() != -1) {
            params.putLong(PURCHASE_DATE, item.getPurchaseDate());
        }
        if (item.getPricePaid() != -1) {
            params.putInt(PRICE_PAID, item.getPricePaid());
        }
        if (item.getDiscount() != -1) {
            params.putInt(DISCOUNT, item.getDiscount());
        }
        if (item.getExpiry() != -1) {
            params.putLong(EXPIRY, item.getExpiry());
        }
        if (item.getCategory() != null) {
            params.putString(CATEGORY, item.getCategory());
        }
        if (item.getSubCategory() != null) {
            params.putString(SUB_CATEGORY, item.getSubCategory());
        }
        if (item.getType() != null) {
            params.putString(TYPE, item.getType());
        }
        if (item.getSubType() != null) {
            params.putString(SUB_TYPE, item.getSubType());
        }
        if (item.getSubType2() != null) {
            params.putString(SUB_TYPE2, item.getSubType2());
        }
        if (item.getSubType3() != null) {
            params.putString(SUB_TYPE3, item.getSubType3());
        }
        if (item.getMainColour() != null) {
            params.putString(MAIN_COLOUR, item.getMainColour());
        }
        if (item.getMainColourShade() != null) {
            params.putString(MAIN_COLOUR_SHADE, item.getMainColourShade());
        }
        if (item.getAccentColour() != null) {
            params.putString(ACCENT_COLOUR, item.getAccentColour());
        }
        if (item.getSize() != null) {
            params.putString(SIZE, item.getSize());
        }
        if (item.getBrand() != null) {
            params.putString(BRAND, item.getBrand());
        }
        if (item.getShop() != null) {
            params.putString(SHOP, item.getShop());
        }
        if (item.getDescription() != null) {
            params.putString(DESCRIPTION, item.getDescription());
        }
        if (item.getNote() != null) {
            params.putString(NOTE, item.getNote());
        }
        params.putBoolean(DECEASED, item.getDeceased());
        FirebaseAnalytics.getInstance(context).logEvent(FirebaseAnalytics.Event.VIEW_ITEM, params);
    }

    public static void logEventExpireItem(Context context, Item item) {
        Bundle params = new Bundle();
        if (item.getPurchaseDate() != -1) {
            params.putLong(PURCHASE_DATE, item.getPurchaseDate());
        }
        if (item.getPricePaid() != -1) {
            params.putInt(PRICE_PAID, item.getPricePaid());
        }
        if (item.getDiscount() != -1) {
            params.putInt(DISCOUNT, item.getDiscount());
        }
        if (item.getExpiry() != -1) {
            params.putLong(EXPIRY, item.getExpiry());
        }
        if (item.getCategory() != null) {
            params.putString(CATEGORY, item.getCategory());
        }
        if (item.getSubCategory() != null) {
            params.putString(SUB_CATEGORY, item.getSubCategory());
        }
        if (item.getType() != null) {
            params.putString(TYPE, item.getType());
        }
        if (item.getSubType() != null) {
            params.putString(SUB_TYPE, item.getSubType());
        }
        if (item.getSubType2() != null) {
            params.putString(SUB_TYPE2, item.getSubType2());
        }
        if (item.getSubType3() != null) {
            params.putString(SUB_TYPE3, item.getSubType3());
        }
        if (item.getMainColour() != null) {
            params.putString(MAIN_COLOUR, item.getMainColour());
        }
        if (item.getMainColourShade() != null) {
            params.putString(MAIN_COLOUR_SHADE, item.getMainColourShade());
        }
        if (item.getAccentColour() != null) {
            params.putString(ACCENT_COLOUR, item.getAccentColour());
        }
        if (item.getSize() != null) {
            params.putString(SIZE, item.getSize());
        }
        if (item.getBrand() != null) {
            params.putString(BRAND, item.getBrand());
        }
        if (item.getShop() != null) {
            params.putString(SHOP, item.getShop());
        }
        if (item.getDescription() != null) {
            params.putString(DESCRIPTION, item.getDescription());
        }
        if (item.getNote() != null) {
            params.putString(NOTE, item.getNote());
        }
        params.putBoolean(DECEASED, item.getDeceased());
        FirebaseAnalytics.getInstance(context).logEvent(EXPIRE_ITEM, params);
    }

    public static void logEventUndoExpireItem(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(UNDO_EXPIRE_ITEM, null);
    }

    public static void logEventEditItem(Context context, Item item) {
        Bundle params = new Bundle();
        if (item.getPurchaseDate() != -1) {
            params.putLong(PURCHASE_DATE, item.getPurchaseDate());
        }
        if (item.getPricePaid() != -1) {
            params.putInt(PRICE_PAID, item.getPricePaid());
        }
        if (item.getDiscount() != -1) {
            params.putInt(DISCOUNT, item.getDiscount());
        }
        if (item.getExpiry() != -1) {
            params.putLong(EXPIRY, item.getExpiry());
        }
        if (item.getCategory() != null) {
            params.putString(CATEGORY, item.getCategory());
        }
        if (item.getSubCategory() != null) {
            params.putString(SUB_CATEGORY, item.getSubCategory());
        }
        if (item.getType() != null) {
            params.putString(TYPE, item.getType());
        }
        if (item.getSubType() != null) {
            params.putString(SUB_TYPE, item.getSubType());
        }
        if (item.getSubType2() != null) {
            params.putString(SUB_TYPE2, item.getSubType2());
        }
        if (item.getSubType3() != null) {
            params.putString(SUB_TYPE3, item.getSubType3());
        }
        if (item.getMainColour() != null) {
            params.putString(MAIN_COLOUR, item.getMainColour());
        }
        if (item.getMainColourShade() != null) {
            params.putString(MAIN_COLOUR_SHADE, item.getMainColourShade());
        }
        if (item.getAccentColour() != null) {
            params.putString(ACCENT_COLOUR, item.getAccentColour());
        }
        if (item.getSize() != null) {
            params.putString(SIZE, item.getSize());
        }
        if (item.getBrand() != null) {
            params.putString(BRAND, item.getBrand());
        }
        if (item.getShop() != null) {
            params.putString(SHOP, item.getShop());
        }
        if (item.getDescription() != null) {
            params.putString(DESCRIPTION, item.getDescription());
        }
        if (item.getNote() != null) {
            params.putString(NOTE, item.getNote());
        }
        params.putBoolean(DECEASED, item.getDeceased());
        FirebaseAnalytics.getInstance(context).logEvent(EDIT_ITEM, params);
    }

    public static void logEventTakeItemPhoto(Context context, Item item) {
        Bundle params = new Bundle();
        if (item.getPurchaseDate() != -1) {
            params.putLong(PURCHASE_DATE, item.getPurchaseDate());
        }
        if (item.getPricePaid() != -1) {
            params.putInt(PRICE_PAID, item.getPricePaid());
        }
        if (item.getDiscount() != -1) {
            params.putInt(DISCOUNT, item.getDiscount());
        }
        if (item.getExpiry() != -1) {
            params.putLong(EXPIRY, item.getExpiry());
        }
        if (item.getCategory() != null) {
            params.putString(CATEGORY, item.getCategory());
        }
        if (item.getSubCategory() != null) {
            params.putString(SUB_CATEGORY, item.getSubCategory());
        }
        if (item.getType() != null) {
            params.putString(TYPE, item.getType());
        }
        if (item.getSubType() != null) {
            params.putString(SUB_TYPE, item.getSubType());
        }
        if (item.getSubType2() != null) {
            params.putString(SUB_TYPE2, item.getSubType2());
        }
        if (item.getSubType3() != null) {
            params.putString(SUB_TYPE3, item.getSubType3());
        }
        if (item.getMainColour() != null) {
            params.putString(MAIN_COLOUR, item.getMainColour());
        }
        if (item.getMainColourShade() != null) {
            params.putString(MAIN_COLOUR_SHADE, item.getMainColourShade());
        }
        if (item.getAccentColour() != null) {
            params.putString(ACCENT_COLOUR, item.getAccentColour());
        }
        if (item.getSize() != null) {
            params.putString(SIZE, item.getSize());
        }
        if (item.getBrand() != null) {
            params.putString(BRAND, item.getBrand());
        }
        if (item.getShop() != null) {
            params.putString(SHOP, item.getShop());
        }
        if (item.getDescription() != null) {
            params.putString(DESCRIPTION, item.getDescription());
        }
        if (item.getNote() != null) {
            params.putString(NOTE, item.getNote());
        }
        params.putBoolean(DECEASED, item.getDeceased());
        FirebaseAnalytics.getInstance(context).logEvent(TAKE_ITEM_PHOTO, params);
    }

    public static void logEventSelectItemImage(Context context, Item item) {
        Bundle params = new Bundle();
        if (item.getPurchaseDate() != -1) {
            params.putLong(PURCHASE_DATE, item.getPurchaseDate());
        }
        if (item.getPricePaid() != -1) {
            params.putInt(PRICE_PAID, item.getPricePaid());
        }
        if (item.getDiscount() != -1) {
            params.putInt(DISCOUNT, item.getDiscount());
        }
        if (item.getExpiry() != -1) {
            params.putLong(EXPIRY, item.getExpiry());
        }
        if (item.getCategory() != null) {
            params.putString(CATEGORY, item.getCategory());
        }
        if (item.getSubCategory() != null) {
            params.putString(SUB_CATEGORY, item.getSubCategory());
        }
        if (item.getType() != null) {
            params.putString(TYPE, item.getType());
        }
        if (item.getSubType() != null) {
            params.putString(SUB_TYPE, item.getSubType());
        }
        if (item.getSubType2() != null) {
            params.putString(SUB_TYPE2, item.getSubType2());
        }
        if (item.getSubType3() != null) {
            params.putString(SUB_TYPE3, item.getSubType3());
        }
        if (item.getMainColour() != null) {
            params.putString(MAIN_COLOUR, item.getMainColour());
        }
        if (item.getMainColourShade() != null) {
            params.putString(MAIN_COLOUR_SHADE, item.getMainColourShade());
        }
        if (item.getAccentColour() != null) {
            params.putString(ACCENT_COLOUR, item.getAccentColour());
        }
        if (item.getSize() != null) {
            params.putString(SIZE, item.getSize());
        }
        if (item.getBrand() != null) {
            params.putString(BRAND, item.getBrand());
        }
        if (item.getShop() != null) {
            params.putString(SHOP, item.getShop());
        }
        if (item.getDescription() != null) {
            params.putString(DESCRIPTION, item.getDescription());
        }
        if (item.getNote() != null) {
            params.putString(NOTE, item.getNote());
        }
        params.putBoolean(DECEASED, item.getDeceased());
        FirebaseAnalytics.getInstance(context).logEvent(SELECT_ITEM_IMAGE, params);
    }

    public static void logEventRemoveItemImage(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(REMOVE_ITEM_IMAGE, null);
    }

    public static void logEventDeleteItem(Context context, Item item) {
        if (item != null) {
            Bundle params = new Bundle();
            if (item.getPurchaseDate() != -1) {
                params.putLong(PURCHASE_DATE, item.getPurchaseDate());
            }
            if (item.getPricePaid() != -1) {
                params.putInt(PRICE_PAID, item.getPricePaid());
            }
            if (item.getDiscount() != -1) {
                params.putInt(DISCOUNT, item.getDiscount());
            }
            if (item.getExpiry() != -1) {
                params.putLong(EXPIRY, item.getExpiry());
            }
            if (item.getCategory() != null) {
                params.putString(CATEGORY, item.getCategory());
            }
            if (item.getSubCategory() != null) {
                params.putString(SUB_CATEGORY, item.getSubCategory());
            }
            if (item.getType() != null) {
                params.putString(TYPE, item.getType());
            }
            if (item.getSubType() != null) {
                params.putString(SUB_TYPE, item.getSubType());
            }
            if (item.getSubType2() != null) {
                params.putString(SUB_TYPE2, item.getSubType2());
            }
            if (item.getSubType3() != null) {
                params.putString(SUB_TYPE3, item.getSubType3());
            }
            if (item.getMainColour() != null) {
                params.putString(MAIN_COLOUR, item.getMainColour());
            }
            if (item.getMainColourShade() != null) {
                params.putString(MAIN_COLOUR_SHADE, item.getMainColourShade());
            }
            if (item.getAccentColour() != null) {
                params.putString(ACCENT_COLOUR, item.getAccentColour());
            }
            if (item.getSize() != null) {
                params.putString(SIZE, item.getSize());
            }
            if (item.getBrand() != null) {
                params.putString(BRAND, item.getBrand());
            }
            if (item.getShop() != null) {
                params.putString(SHOP, item.getShop());
            }
            if (item.getDescription() != null) {
                params.putString(DESCRIPTION, item.getDescription());
            }
            if (item.getNote() != null) {
                params.putString(NOTE, item.getNote());
            }
            params.putBoolean(DECEASED, item.getDeceased());
            FirebaseAnalytics.getInstance(context).logEvent(DELETE_ITEM, params);
        } else {
            FirebaseAnalytics.getInstance(context).logEvent(DELETE_ITEM, null);
        }
    }

    public static void logEventUndoDeleteItem(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(UNDO_DELETE_ITEM, null);
    }

    public static void logEventSortExpired(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(SORT_EXPIRED, null);
    }

    public static void logEventSortPurchaseDate(Context context) {
        FirebaseAnalytics.getInstance(context).logEvent(SORT_PURCHASE_DATE, null);
    }
} public class ItemWidgetProvider extends AppWidgetProvider {

    public static final String ACTION_DATA_UPDATED = "data_updated";
    public static final String ACTION_EDIT_NEW_ITEM = "action_edit_new_item";

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        if (intent.getAction().equals(ACTION_DATA_UPDATED)) {
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
            int[] appWidgetIds = appWidgetManager.getAppWidgetIds(
                    new ComponentName(context, getClass()));
            appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_list);
        }
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        boolean largeScreen = context.getResources().getBoolean(R.bool.large_layout);
        for (int appWidgetId : appWidgetIds) {
            RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget);

            // WidgetListService intent for populating collection views.
            Intent collectionIntent = new Intent(context, WidgetListService.class);
            rv.setRemoteAdapter(R.id.widget_list, collectionIntent);
            rv.setEmptyView(R.id.widget_list, R.id.widget_empty);

            // Intent for opening the main app from the widget title.
            Intent itemReaperIntent = new Intent(context, ItemsActivity.class);
            PendingIntent itemReaperPendingIntent = PendingIntent.getActivity(context, 0,
                    itemReaperIntent, 0);
            rv.setOnClickPendingIntent(R.id.widget_title, itemReaperPendingIntent);

            // Intent for adding an item when clicking the add item button.
            Intent addItemIntent = largeScreen
                    ? new Intent(context, ItemsActivity.class)
                    : new Intent(context, EditItemActivity.class);
            addItemIntent.putExtra(EXTRA_EDIT_NEW_ITEM, true);
            addItemIntent.setAction(ACTION_EDIT_NEW_ITEM);
            PendingIntent addItemPendingIntent = TaskStackBuilder.create(context)
                    .addNextIntentWithParentStack(addItemIntent)
                    .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
            rv.setOnClickPendingIntent(R.id.widget_add_item, addItemPendingIntent);

            // Collection for ItemDetailsActivity intent when opening individual list item.
            Intent clickIntentTemplate = largeScreen
                    ? new Intent(context, ItemsActivity.class)
                    : new Intent(context, ItemDetailsActivity.class);
            PendingIntent clickPendingIntentTemplate = TaskStackBuilder.create(context)
                    .addNextIntentWithParentStack(clickIntentTemplate)
                    .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
            rv.setPendingIntentTemplate(R.id.widget_list, clickPendingIntentTemplate);
            appWidgetManager.updateAppWidget(appWidgetId, rv);
        }
    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        super.onDeleted(context, appWidgetIds);
        for (int appWidgetId : appWidgetIds) {
            RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget);
            rv.removeAllViews(appWidgetId);
        }
    }
} public static final String EXTRA_DELETED_ITEM = "deleted_item"; public static final int SORT_BY_EXPIRY = 0; public static final int SORT_BY_PURCHASE_DATE = 1; public static final int REQUEST_CODE_SIGNIN = 3; public static SimpleDateFormat getDateFormat(String format) {
    return new SimpleDateFormat(format, Locale.ENGLISH);
} public static String getPriceFromTotalCents(int totalCents) {
    int dollars = totalCents / 100;
    int cents = totalCents % 100;
    String centsString = cents > 9
            ? String.valueOf(cents)
            : "0" + cents;
    return cents == 0
            ? String.valueOf(dollars)
            : dollars + "." + centsString;
}
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BaseTransientBottomBar;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
import com.google.common.collect.ImmutableList;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.michaelvescovo.android.itemreaper.R;
import com.michaelvescovo.android.itemreaper.SharedPreferencesHelper;
import com.michaelvescovo.android.itemreaper.auth.AuthActivity;
import com.michaelvescovo.android.itemreaper.data.Item;
import com.michaelvescovo.android.itemreaper.settings.SettingsActivity;
import com.michaelvescovo.android.itemreaper.util.Analytics;
import com.michaelvescovo.android.itemreaper.widget.ItemWidgetProvider;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
import static com.michaelvescovo.android.itemreaper.R.id.expiry;
import static com.michaelvescovo.android.itemreaper.items.ItemsActivity.EXTRA_DELETED_ITEM;
import static com.michaelvescovo.android.itemreaper.items.SortItemsDialogFragment.SORT_BY_EXPIRY;
import static com.michaelvescovo.android.itemreaper.items.SortItemsDialogFragment.SORT_BY_PURCHASE_DATE;
import static com.michaelvescovo.android.itemreaper.util.Constants.REQUEST_CODE_SIGNIN;
import static com.michaelvescovo.android.itemreaper.util.MiscHelperMethods.getDateFormat;
import static com.michaelvescovo.android.itemreaper.util.MiscHelperMethods.getPriceFromTotalCents;
            updateWidget();
        } else {
            if (sortBy == SORT_BY_EXPIRY) {
                mItemsAdapter.sortItemsByExpiry();
                mItemsAdapter.notifyDataSetChanged();
            } else if (sortBy == SORT_BY_PURCHASE_DATE) {
                mItemsAdapter.sortItemsByPurchaseDate();
                mItemsAdapter.notifyDataSetChanged();
            }
        }
    }

    private void updateWidget() {
        Intent updateWidgetIntent = new Intent(getContext(), ItemWidgetProvider.class);
        updateWidgetIntent.setAction(ItemWidgetProvider.ACTION_DATA_UPDATED);
        getContext().sendBroadcast(updateWidgetIntent);
    }

    private void configureSnackbarForDeletedItem() {
        final boolean[] snackbarShown = {false};
        if (mDeletedItem != null) {
            Snackbar snackbar = mCallback.onShowSnackbar(getString(R.string.delete_item_success),
                    Snackbar.LENGTH_LONG);
            snackbar.setAction(R.string.delete_item_undo, new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mPresenter.restoreItem(mDeletedItem);
                    mDeletedItem = null;
                    Snackbar snackbarRestored = mCallback.onShowSnackbar(
                            getString(R.string.delete_item_undo_success), Snackbar.LENGTH_LONG);
                    snackbarRestored.show();
                    Analytics.logEventUndoDeleteItem(getContext());
                }
            });
            snackbar.addCallback(new BaseTransientBottomBar.BaseCallback<Snackbar>() {
                @Override
                public void onDismissed(Snackbar transientBottomBar, int event) {
                    super.onDismissed(transientBottomBar, event);
                    // There seems to be a bug where onDismissed is called before onShown.
                    if (snackbarShown[0]) {
                        if (mDeletedItem != null) {
                            removeImageFromFirebase();
                            mDeletedItem = null;
                        }
                    }
                }

                @Override
                public void onShown(Snackbar transientBottomBar) {
                    super.onShown(transientBottomBar);
                    snackbarShown[0] = true;
                }
            });
            snackbar.show();
        }
    }

    private void removeImageFromFirebase() {
        if (mDeletedItem.getImageUrl() != null) {
            if (mDeletedItem.getImageUrl().contains("https://firebasestorage")) {
                StorageReference photoRef = mFirebaseStorage.getReferenceFromUrl(
                        mDeletedItem.getImageUrl());
                photoRef.delete();
            }
        }
    }

    public void onItemDeleted(@NonNull Item item) {
        mDeletedItem = item;
        if (mLargeScreen) {
            onResume();
        }
    }

    public void searchItem(@Nullable String query) {
        mQuery = query;
        mSearching = mQuery != null;
        mPresenter.getItems(mCurrentSort);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mCallback = (Callback) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement callback");
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mMediaPlayer != null) {
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallback = null;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_sort:
                mCallback.onSortSelected(mSharedPreferencesHelper);
                break;
            case R.id.action_about:
                mPresenter.openAbout();
                break;
            case R.id.action_sign_out:
                mPresenter.openSignOut();
                Analytics.logEventLogout(getContext());
                break;
            case R.id.action_settings:
                Intent intent = new Intent(getContext(), SettingsActivity.class);