public class Post extends ViewItem implements Comparable<ViewItem> {
    @Nullable
    private String description;
    private String title;
    private PostType postType;
    @Nullable
    private Drawable thumbnail;
    @Nullable
    private String thumbnailUrl;
    @Nullable
    private String thumbnailHDUrl;
    @Nullable
    private String username;
    
    private long api_ID;
    private int duration;
    private String url;
    private boolean isThumbnailHD = false;

    private Post(PostBuilder builder) {
        super(ViewItem.TYPE_POST, builder.date);
        description = builder.description;
        title = builder.title;
        postType = builder.postType;
        thumbnailUrl = builder.thumbnailUrl;
        thumbnailHDUrl = builder.thumbnailHDUrl;
        username = builder.username;
        duration = builder.duration;
        url = builder.url;
        api_ID = builder.api_ID;
    }

    @Nullable
    public Drawable getThumbnail() {
        return this.thumbnail;
    }

    public void setThumbnail(@Nullable Drawable thumbnail) {
        this.thumbnail = thumbnail;
    }

    public boolean isThumbnailHD() { return isThumbnailHD; }

    public void setIsThumbnailHD(boolean isHD) { this.isThumbnailHD = isHD; }

    @Nullable
    public String getThumbnailUrl() {
        return thumbnailUrl;
    }

    @Nullable
    public String getThumbnailHDUrl() {
        return thumbnailHDUrl;
    }

    public PostType getPostType() {
        return postType;
    }

    @Nullable
    public String getUsername() { return username; }

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

    public long getId() {
        return api_ID;
    }

    public String getTitle() {
        return title;
    }

    public int getDuration() {
        return duration;
    }

    public String getUrl() {
        return url;
    }

    @Override
    public int hashCode() {
        int result = 5;
        int random = 87;
        result = random * result + (getTitle() != null ? getTitle().hashCode() : 0);
        result = random * result + (getDescription() != null ? getDescription().hashCode() : 0);
        result = random * result + Long.valueOf(getDate().getTime()).intValue();
        result = random * result + getPostType().ordinal();
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (this.getClass() != obj.getClass()) return false;

        Post other = (Post) obj;
        if (this.getDescription() != null) {
            if (other.getDescription() == null) return false;
            if (!this.getDescription().equals(other.getDescription())) return false;
        } else if (other.getDescription() != null) return false;

        if (this.getTitle() != null) {
            if (other.getTitle() == null) return false;
            if (!this.getTitle().equals(other.getTitle())) return false;
        } else if (other.getTitle() != null) return false;

        if (this.getDate().getTime() != other.getDate().getTime()) return false;
        else if (this.getPostType() != other.getPostType()) return false;
        return true;
    }

    @SuppressWarnings("UnusedReturnValue")
    public static class PostBuilder implements Comparable<PostBuilder> {
        private boolean empty = false;
        private String title;
        private PostType postType;
        @Nullable
        private String description;
        @Nullable
        private String thumbnailUrl;
        @Nullable
        private String thumbnailHDUrl;
        @Nullable
        private String username;
        private long api_ID;
        private Date date;
        private int duration;
        private String url;


        public PostBuilder( PostType postType ) {
            this.postType = postType;
        }

        public PostBuilder empty(){
            empty = true;
            return this;
        }

        public Date getDate() {
            return date;
        }

        public PostBuilder description(@Nullable String description) {
            this.description = description;
            return this;
        }

        public PostBuilder username(@Nullable String username) {
            this.username = username;
            return this;
        }

        public PostBuilder title(String title) {
            this.title = title;
            return this;
        }

        public PostBuilder thumbnailUrl(@Nullable String thumbnailUrl) {
            this.thumbnailUrl = thumbnailUrl;
            return this;
        }

        public PostBuilder thumbnailHDUrl(@Nullable String thumbnailHDUrl) {
            this.thumbnailHDUrl = thumbnailHDUrl;
            return this;
        }

        public PostBuilder id(long api_ID) {
            this.api_ID = api_ID;
            return this;
        }

        public PostBuilder date(Date date) {
            this.date = date;
            return this;
        }

        public PostBuilder duration(int duration) {
            this.duration = duration;
            return this;
        }

        public PostBuilder url(String url) {
            this.url = url;
            return this;
        }

        public Post build() {
            if (empty){
                return null;
            }
            if (title == null || title.isEmpty()) {
                PsLog.e("Title is not given");
                return null;
            }
            if (date == null) {
                PsLog.e("Date is not given");
                return null;
            }
            if (postType == PostType.UPLOADPLAN && (description == null || description.isEmpty())) {
                PsLog.e("Uploadplan with no description");
                return null;
            }

            if(postType == null){
                PsLog.e("Not a valid type!");
                return null;
            }
            return new Post(this);
        }

        @Override
        public int compareTo(@NonNull PostBuilder post) {
            if( post.getDate().getTime() > this.date.getTime() ) {
                return 1;
            } else if ( post.getDate().getTime() < this.getDate().getTime() ) {
                return -1;
            }
            return 0;
        }
    }

    public enum PostType {
        YOUTUBE(YoutubeRepository.class, "Youtube", R.id.nav_video_yt, R.color.youtube),
        PS_VIDEO(FirebaseRepository.class, "PS.de Videos", R.id.nav_video_ps, R.color.pietsmiet),
        PIETCAST(FirebaseRepository.class, "Pietcast", R.id.nav_pietcast, R.color.pietsmiet),
        TWITTER(TwitterRepository.class, "Twitter", R.id.nav_twitter, R.color.twitter),
        FACEBOOK(FacebookRepository.class, "Facebook", R.id.nav_facebook, R.color.facebook),
        UPLOADPLAN(FirebaseRepository.class, "Uploadplan", R.id.nav_upload_plan, R.color.pietsmiet),
        NEWS(FirebaseRepository.class, "PS.de News", R.id.nav_ps_news, R.color.pietsmiet);
        public final String name;
        public final Class<? extends MainRepository> aClass;
        public final int drawerId;
        public final int colorId;

        public static PostType getByDrawerId(int did) {
            for (PostType p: values()) {
                if(p.drawerId == did) return p;
            }
            return null;
        }

        /***
         * Creates a PostType.
         * @param aClass The Class Object
         * @param name The name
         * @param drawerId Resource drawer id
         * @param colorId Resource color id
         */
        PostType(Class<? extends MainRepository> aClass, String name, int drawerId, int colorId) {
            this.aClass = aClass;
            this.name = name;
            this.drawerId = drawerId;
            this.colorId = colorId;
        }
    }
} @SuppressWarnings("SameParameterValue")
public interface FirebaseApiInterface {
    // Get all scopes (with specific dates)
    @GET(".json")
    Observable<Map<String, Map<String, FirebaseItem>>> getAll();

    @GET(".json?orderBy=\"date\"")
    Observable<Map<String, Map<String, FirebaseItem>>> getAllSince(@Query("startAt") long fromTime);

    @GET(".json?orderBy=\"date\"")
    Observable<Map<String, Map<String, FirebaseItem>>> getAllUntil(@Query("endAt") long untilTime,
                                                                   @Query("limitToLast") int limit);

    // Get a single scope (with specific dates)
    @GET("{scope}.json")
    Observable<Map<String, FirebaseItem>> getScopeAll(@Path("scope") String scope);

    @GET("{scope}.json?orderBy=\"date\"")
    Observable<Map<String, FirebaseItem>> getScopeSince(@Path("scope") String scope,
                                                        @Query("startAt") long fromTime);

    @GET("{scope}.json?orderBy=\"date\"")
    Observable<Map<String, FirebaseItem>> getScopeUntil(@Path("scope") String scope,
                                                        @Query("endAt") long untilTime,
                                                        @Query("limitToLast") int limit);
} public abstract class RetrofitHelper {
    private static OkHttpClient client;

    public static Retrofit getRetrofit(String url) {
        if (client == null) {
            client = StethoHelper.configureInterceptor(new OkHttpClient.Builder()).build();
        }
        RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io());

        return new Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .addCallAdapterFactory(rxAdapter)
                .build();
    }
} public class SettingsHelper {
    public static boolean boolAppFirstRun;

    public static boolean boolUploadplanNotification;
    public static boolean boolVideoNotification;
    public static boolean boolNewsNotification;
    public static boolean boolPietcastNotification;

    //SWITCHES
    public static boolean boolCategoryYoutubeVideos;
    public static boolean boolCategoryPietsmietVideos;
    public static boolean boolCategoryPietsmietNews;
    public static boolean boolCategoryPietsmietUploadplan;
    public static boolean boolCategoryPietcast;
    public static boolean boolCategoryTwitter;
    public static boolean boolCategoryFacebook;

    public static String stringTwitterBearer;
    public static String stringFirebaseDbUrl;
    public static String stringFeedbackUrl;
    public static String stringPietstreamUrl;
    public static String stringTwitchChannelIDPietstream;

    public static int intQualityLoadHDImages;
    public static final int TYPE_HD_NEVER = 0;
    public static final int TYPE_HD_WIFI = 1;
    public static final int TYPE_HD_ALWAYS = 2;

    public static void loadAllSettings(Context context) {
        FirebaseRemoteConfig mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();

        boolAppFirstRun = getSharedPreferenceBoolean(context, KEY_APP_FIRST_RUN, true);

        boolUploadplanNotification = getSharedPreferenceBoolean(context, KEY_NOTIFY_UPLOADPLAN_SETTING, true);
        boolVideoNotification = getSharedPreferenceBoolean(context, KEY_NOTIFY_VIDEO_SETTING, false);
        boolNewsNotification = getSharedPreferenceBoolean(context, KEY_NOTIFY_NEWS_SETTING, false);
        boolPietcastNotification = getSharedPreferenceBoolean(context, KEY_NOTIFY_PIETCAST_SETTING, false);
        stringTwitterBearer = getSharedPreferenceString(context, KEY_TWITTER_BEARER, null);
        stringFirebaseDbUrl = mFirebaseRemoteConfig.getString("FIREBASE_DB_URL");
        stringFeedbackUrl = mFirebaseRemoteConfig.getString("url_feedback");
        stringPietstreamUrl = mFirebaseRemoteConfig.getString("url_pietstream");
        stringTwitchChannelIDPietstream = mFirebaseRemoteConfig.getString("twitch_channel_id_pietstream");
        intQualityLoadHDImages = getSharedPreferenceInt(context, KEY_QUALITY_IMAGE_LOAD_HD_SETTING, TYPE_HD_ALWAYS);

        // SWITCHES
        boolCategoryYoutubeVideos = getSharedPreferenceBoolean(context, KEY_CATEGORY_YOUTUBE_VIDEOS, false);
        boolCategoryPietsmietVideos = getSharedPreferenceBoolean(context, KEY_CATEGORY_PIETSMIET_VIDEOS, true);
        boolCategoryPietsmietNews = getSharedPreferenceBoolean(context, KEY_CATEGORY_PIETSMIET_NEWS, true);
        boolCategoryPietsmietUploadplan = getSharedPreferenceBoolean(context, KEY_CATEGORY_PIETSMIET_UPLOADPLAN, true);
        boolCategoryPietcast = getSharedPreferenceBoolean(context, KEY_CATEGORY_PIETCAST, true);
        boolCategoryTwitter = getSharedPreferenceBoolean(context, KEY_CATEGORY_TWITTER, true);
        boolCategoryFacebook = getSharedPreferenceBoolean(context, KEY_CATEGORY_FACEBOOK, true);
    }

    public static boolean shouldLoadHDImages(Context c) {
        return intQualityLoadHDImages == TYPE_HD_ALWAYS ||
                (intQualityLoadHDImages == TYPE_HD_WIFI && new NetworkUtil(c).isConnectedWifi());
    }

    public static String getSharedPreferenceKeyForType(Post.PostType type) {
        switch (type) {
            case PS_VIDEO:
                return KEY_CATEGORY_PIETSMIET_VIDEOS;
            case YOUTUBE:
                return KEY_CATEGORY_YOUTUBE_VIDEOS;
            case PIETCAST:
                return KEY_CATEGORY_PIETCAST;
            case TWITTER:
                return KEY_CATEGORY_TWITTER;
            case FACEBOOK:
                return KEY_CATEGORY_FACEBOOK;
            case UPLOADPLAN:
                return KEY_CATEGORY_PIETSMIET_UPLOADPLAN;
            case NEWS:
                return KEY_CATEGORY_PIETSMIET_NEWS;
            default:
                return "";
        }
    }

    public static boolean getSettingsValueForType(Post.PostType type) {
        switch (type) {
            case PS_VIDEO:
                return boolCategoryPietsmietVideos;
            case YOUTUBE:
                return boolCategoryYoutubeVideos;
            case PIETCAST:
                return boolCategoryPietcast;
            case TWITTER:
                return boolCategoryTwitter;
            case FACEBOOK:
                return boolCategoryFacebook;
            case UPLOADPLAN:
                return boolCategoryPietsmietUploadplan;
            case NEWS:
                return boolCategoryPietsmietNews;
            default:
                return true;
        }
    }


    public static boolean isOnlyType(Post.PostType type) {
        for (Post.PostType i : Post.PostType.values()) {
            if (getSettingsValueForType(i) && i != type) return false;
        }
        return true;
    }

}
 public class MainActivity extends BaseActivity implements MainActivityView, NavigationView.OnNavigationItemSelectedListener {
    public static final int RESULT_CLEAR_CACHE = 17;
    public static final int REQUEST_SETTINGS = 16;
    private static final long MAX_TWITCH_CHECK_TIME_DIFF = 5 * TimeUtils.MINUTE_MILLIS;
    private static final long MAX_INACTIVITY_TIME_TO_RELOAD = 15 * TimeUtils.MINUTE_MILLIS;

    private CustomTabActivityHelper mCustomTabActivityHelper;

    private boolean CLEAR_CACHE_FLAG_DRAWER = false;

    private long lastDateCheckedTwitch;

    private CardViewAdapter adapter;
    @BindView(R.id.dl_root)
    DrawerLayout mDrawer;
    @BindView(R.id.nav_view)
    NavigationView mNavigationView;
    public EndlessScrollListener scrollListener;
    @BindView(R.id.swipeContainer)
    SwipeRefreshLayout refreshLayout;
    @BindView(R.id.btnToTop)
    FloatingActionButton fabToTop;
    @BindView(R.id.cardList)
    RecyclerView recyclerView;
    private MenuItem pietstream_banner;

    private PostPresenter postPresenter;
    private long exitTime;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FirebaseUtil.disableCollectionOnDebug(this.getApplicationContext());
        StethoHelper.init(this);

        FirebaseUtil.loadRemoteConfig();
        ButterKnife.bind(this);
        SettingsHelper.loadAllSettings(this);
        FirebaseUtil.setupTopicSubscriptions();

        setupToolbar(null);

        mCustomTabActivityHelper = new CustomTabActivityHelper();

        postPresenter = new PostPresenter(this,
                new PostRepositoryImpl(this),
                DatabaseHelper.getInstance(this.getApplicationContext()),
                new NetworkUtil(this.getApplicationContext()),
                this.getApplicationContext());

        setupNotificationChannels();
        setupRecyclerView();
        setupDrawer();

        refreshLayout.setOnRefreshListener(() -> postPresenter.fetchNewPosts());
        refreshLayout.setProgressViewOffset(false, -130, 80); //todo Find another way. Just added to support Android 4.x
        refreshLayout.setColorSchemeColors(getResources().getColor(R.color.pietsmiet));
        refreshLayout.setColorSchemeResources(R.color.colorPrimary, R.color.pietsmiet, R.color.colorPrimaryDark);

        // Top Button init
        fabToTop.setVisibility(View.INVISIBLE);
        fabToTop.setOnClickListener(new View.OnClickListener() { //Butter Knife useful?
            @Override
            public void onClick(View v) {
                if (((LinearLayoutManager) recyclerView.getLayoutManager()).findLastVisibleItemPosition() < 85) {
                    recyclerView.smoothScrollToPosition(0);
                } else {
                    recyclerView.scrollToPosition(0);
                }
                fabToTop.hide(new FloatingActionButton.OnVisibilityChangedListener() {
                    @Override
                    public void onHidden(FloatingActionButton fab) {
                        super.onHidden(fab);
                        fab.setVisibility(View.INVISIBLE);
                    }
                });
            }
        });
        // End Top Button init

        if (SettingsHelper.boolAppFirstRun) {
            displayNotificationSelection();

            // Set AppFirstRun to false //todo maybe position this in OnDestroy / OnPause, because of logic
            SettingsHelper.boolAppFirstRun = false;
            SharedPreferenceHelper.setSharedPreferenceBoolean(this, KEY_APP_FIRST_RUN, false);
        }
        new SecretConstants(this);
    }

    private void setupNotificationChannels() {
        if (Build.VERSION.SDK_INT >= 26) {
            NotificationManager mNotificationManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            String id = "Default";
            CharSequence name = getString(R.string.channel_default_name);
            String description = getString(R.string.channel_default_description);
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel mChannel = new NotificationChannel(id, name, importance);
            mChannel.setDescription(description);
            mChannel.enableLights(true);
            mChannel.setLightColor(getResources().getColor(R.color.pietsmiet));
            mChannel.enableVibration(true);
            mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
            mNotificationManager.createNotificationChannel(mChannel);
        }
    }

    private void displayNotificationSelection() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(R.string.dialog_video_notification)
                .setPositiveButton(R.string.yes, (dialog, id) -> {
                    SettingsHelper.boolVideoNotification = true;
                    SharedPreferenceHelper.setSharedPreferenceBoolean(this, KEY_NOTIFY_VIDEO_SETTING, true);
                    FirebaseUtil.setFirebaseTopicSubscription(FirebaseUtil.TOPIC_VIDEO, true);
                })
                .setNegativeButton(R.string.no, (dialog, id) -> {
                    SettingsHelper.boolVideoNotification = false;
                    SharedPreferenceHelper.setSharedPreferenceBoolean(this, KEY_NOTIFY_VIDEO_SETTING, false);
                    FirebaseUtil.setFirebaseTopicSubscription(FirebaseUtil.TOPIC_VIDEO, false);
                });
        builder.create().show();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (postPresenter != null) postPresenter.stopSubscriptions();
        if (refreshLayout != null) refreshLayout.setRefreshing(false);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Serializable serCategory = getIntent().getSerializableExtra(MyFirebaseMessagingService.EXTRA_TYPE);
        if (serCategory instanceof Post.PostType) {
            Post.PostType category = (Post.PostType) serCategory;
            // As this code is onStart, remove the intent to avoid that it'll execute again
            getIntent().removeExtra(MyFirebaseMessagingService.EXTRA_TYPE);
            // Log an event to firebase
            Bundle bundle = new Bundle();
            // TODO rework bundle to not have to send ints -> dont use ordinals -> they can change -> Error
            bundle.putInt(FirebaseAnalytics.Param.ITEM_NAME, category.ordinal());
            FirebaseAnalytics.getInstance(this).logEvent("notification_clicked", bundle);
            // Select the category in the drawer (this will update sharedPrefs too)
            onNavigationItemSelected(mNavigationView.getMenu().findItem(category.drawerId));
            // Update settings from sharedPrefs
            SettingsHelper.loadAllSettings(getBaseContext());
            // Fetch posts based on the new settings
            if(postPresenter.getPostsToDisplay().size() > 0) {
                postPresenter.fetchNewPosts();
            } else {
                postPresenter.fetchNextPosts();
            }
        } else if (postPresenter.getPostsToDisplay().isEmpty()) {
            // Load posts from db
            DatabaseHelper.getInstance(this).displayPostsFromCache(postPresenter);
        } else if ((exitTime - System.currentTimeMillis()) > MAX_INACTIVITY_TIME_TO_RELOAD) {
            // Auto reload posts if going back to activity after the time specified in MAX_INACTIVITY_TIME_TO_RELOAD
            postPresenter.fetchNewPosts();
        }
        mCustomTabActivityHelper.bindCustomTabsService(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        exitTime = System.currentTimeMillis();
        mCustomTabActivityHelper.unbindCustomTabsService(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        if (postPresenter != null) postPresenter.stopSubscriptions();
        if (refreshLayout != null) refreshLayout.setRefreshing(false);
        if (scrollListener != null) scrollListener.resetState();
    }

    @Override
    public void onResume() {
        super.onResume();
        SettingsHelper.loadAllSettings(this);
        // Update adapter to refresh timestamps
        refreshAdapter();
    }

    private void setupRecyclerView() {
        adapter = new CardViewAdapter(postPresenter.getPostsToDisplay(), this);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(adapter);

        // Retain an instance so that you can call `resetState()` for fresh searches
        scrollListener = new EndlessScrollListener(layoutManager) {
            @Override
            public void onLoadMore(int totalItemsCount, RecyclerView view) {
                // Triggered only when new data needs to be appended to the list
                postPresenter.fetchNextPosts();
            }
        };
        // Adds the scroll listener to RecyclerView
        recyclerView.addOnScrollListener(scrollListener);
    }

    private void setupDrawer() {
        mNavigationView = findViewById(R.id.nav_view);
        mNavigationView.setNavigationItemSelectedListener(this);
        pietstream_banner = mNavigationView.getMenu().findItem(R.id.nav_pietstream_banner);

        // Iterate through every menu item and save it's state
        for (Post.PostType item : Post.PostType.values()) {
            if (mNavigationView != null) {
                MenuItem mi = mNavigationView.getMenu().findItem(item.drawerId);
                if(mi != null) {
                    Switch checker = (Switch) mi.getActionView();
                    checker.setChecked(SettingsHelper.getSettingsValueForType(item));
                    checker.setOnCheckedChangeListener((view, check) -> {
                        if (check)
                            CLEAR_CACHE_FLAG_DRAWER = true; //todo improve if for example a user just switched on off on -> dont clear cache
                        SharedPreferenceHelper.setSharedPreferenceBoolean(getBaseContext(), SettingsHelper.getSharedPreferenceKeyForType(item), checker.isChecked());
                    });
                }
            }
        }

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawer, mToolbar, R.string.drawer_open, R.string.drawer_close) {
            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
                updatePostsCategoriesFromDrawer();
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                reloadTwitchBanner();
            }
        };
        mDrawer.addDrawerListener(toggle);
        toggle.syncState();
    }

    private void refreshAdapter() {
        Observable.just("")
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(ignored -> {
                            if (recyclerView != null) recyclerView.getRecycledViewPool().clear();
                            if (adapter != null) adapter.notifyDataSetChanged();
                        }
                );
    }

    private void scrollToTop() {
        Observable.just("")
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(ignored -> {
                            if (recyclerView != null) recyclerView.scrollToPosition(0);
                        }
                );
    }

    private void updatePostsCategoriesFromDrawer() {
        SettingsHelper.loadAllSettings(getBaseContext());
        if (CLEAR_CACHE_FLAG_DRAWER) {
            clearCache();
            postPresenter.fetchNextPosts();
            CLEAR_CACHE_FLAG_DRAWER = false;
        } else {
            postPresenter.updateSettingsFilters();
            scrollListener.resetState();
        }
    }

    /**
     * Reloads the stream status and updates the banner in the SideMenu
     */
    // TODO not the right place
    private void reloadTwitchBanner() {
        long current = new Date().getTime();
        if ((current - lastDateCheckedTwitch) > MAX_TWITCH_CHECK_TIME_DIFF) {
            lastDateCheckedTwitch = current;
            Observable<TwitchStream> obsTTV = new TwitchHelper().getStreamStatus(SettingsHelper.stringTwitchChannelIDPietstream);
            obsTTV.subscribe((stream) -> {
                if (stream != null) {
                    pietstream_banner.setVisible(true);
                } else {
                    pietstream_banner.setVisible(false);
                }
            }, (err) -> PsLog.e("Could not update Twitch status", err));
        }
    }

    private void updateAdapterItemRange(int startPosition, int size) {
        Observable.just("")
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(ignored -> {
                            if (adapter != null) adapter.notifyItemRangeInserted(startPosition, size);
                        }
                );
    }

    private void setRefreshAnim(boolean val) {
        Observable.just(val)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(bool -> {
                    if (refreshLayout != null) refreshLayout.setRefreshing(bool);
                });
    }

    public void showMessage(String message, int length, boolean retryLoadingButton, boolean fetchDirectionDown) {
        Observable.just(message)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(msg -> {
                    if (findViewById(R.id.main_layout) != null) {
                        Snackbar sb = Snackbar.make(findViewById(R.id.main_layout), msg, length);
                        if (retryLoadingButton) sb.setAction(R.string.info_retry, (view) -> {
                            scrollListener.resetState();
                            if (fetchDirectionDown) {
                                postPresenter.fetchNextPosts();
                            } else {
                                postPresenter.fetchNewPosts();
                            }
                        });
                        sb.show();
                    } else {
                        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
                    }
                });
    }

    private void clearCache() {
        DatabaseHelper.getInstance(this).clearDB();
        postPresenter.clearPosts();
        refreshAdapter();
        scrollListener.resetState();
        CacheUtil.trimCache(this);
        fabToTop.hide();
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.nav_upload_plan:
            case R.id.nav_facebook:
            case R.id.nav_twitter:
            case R.id.nav_pietcast:
            case R.id.nav_ps_news:
            case R.id.nav_video_ps:
            case R.id.nav_video_yt:
                Post.PostType pt = Post.PostType.getByDrawerId(item.getItemId());
                if (((Switch) item.getActionView()).isChecked() && (pt != null && isOnlyType(pt)) ) {
                    for (Post.PostType z : Post.PostType.values()) {
                        int id = z.drawerId;
                        Switch aSwitch = ((Switch) mNavigationView.getMenu().findItem(id).getActionView());
                        aSwitch.setChecked(true);
                        recyclerView.scrollToPosition(0);
                    }
                } else {
                    for (Post.PostType i : Post.PostType.values()) {
                        int id = i.drawerId;
                        Switch aSwitch = ((Switch) mNavigationView.getMenu().findItem(id).getActionView());
                        if (id == item.getItemId()) {
                            aSwitch.setChecked(true);
                            recyclerView.scrollToPosition(0);
                        } else aSwitch.setChecked(false);
                    }
                }
                break;
            case R.id.nav_feedback:
                LinkUtil.openUrl(this, SettingsHelper.stringFeedbackUrl);
                break;
            case R.id.nav_help:
                startActivity(new Intent(MainActivity.this, AboutActivity.class));
                break;
            case R.id.nav_settings:
                startActivityForResult(new Intent(MainActivity.this, SettingsActivity.class), REQUEST_SETTINGS);
                break;
            case R.id.nav_pietstream_banner:
                LinkUtil.openUrlExternally(this, SettingsHelper.stringPietstreamUrl);
                break;
            default:
                return false;
        }
        // Close the navigation drawer
        mDrawer.closeDrawers();

        return true;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_SETTINGS) {
            SettingsHelper.loadAllSettings(this);
            if (resultCode == RESULT_CLEAR_CACHE) {
                clearCache();
                showMessage(getString(R.string.info_cleared_cache));
            } else {
                // Update adapter to refresh timestamps
                refreshAdapter();
            }
        }
    }


    @Override
    public void freshLoadingCompleted() {
        refreshAdapter();
        setRefreshAnim(false);

        FirebaseAnalytics.getInstance(this).logEvent(FirebaseUtil.EVENT_FRESH_COMPLETED, new Bundle());
    }

    @Override
    public void loadingNextCompleted(int startPosition, int itemCount) {
        updateAdapterItemRange(startPosition, itemCount);
        setRefreshAnim(false);

        Bundle bundle = new Bundle();
        bundle.putInt(FirebaseUtil.PARAM_START_POSITION, startPosition);
        bundle.putInt(FirebaseUtil.PARAM_ITEM_COUNT, itemCount);
        FirebaseAnalytics.getInstance(this).logEvent(FirebaseUtil.EVENT_NEXT_COMPLETED, bundle);
    }

    @Override
    public void loadingNewCompleted(int itemCount) {
        updateAdapterItemRange(0, itemCount);
        setRefreshAnim(false);
        scrollToTop();

        Bundle bundle = new Bundle();
        bundle.putInt(FirebaseUtil.PARAM_ITEM_COUNT, itemCount);
        FirebaseAnalytics.getInstance(this).logEvent(FirebaseUtil.EVENT_NEW_COMPLETED, bundle);
    }

    @Override
    public void noNetworkError() {
        showMessage(getString(R.string.error_no_network));
        scrollListener.resetState();
    }

    @Override
    public void loadingStarted() {
        setRefreshAnim(true);
    }

    @Override
    public void loadingFailed(String message, boolean fetchDirectionDown) {
        showMessage(message, Snackbar.LENGTH_INDEFINITE, true, fetchDirectionDown);
        setRefreshAnim(false);
    }

    @Override
    public void showMessage(String message) {
        showMessage(message, Snackbar.LENGTH_LONG, false, false);
    }
} public enum PostType {
    YOUTUBE(YoutubeRepository.class, "Youtube", R.id.nav_video_yt, R.color.youtube),
    PS_VIDEO(FirebaseRepository.class, "PS.de Videos", R.id.nav_video_ps, R.color.pietsmiet),
    PIETCAST(FirebaseRepository.class, "Pietcast", R.id.nav_pietcast, R.color.pietsmiet),
    TWITTER(TwitterRepository.class, "Twitter", R.id.nav_twitter, R.color.twitter),
    FACEBOOK(FacebookRepository.class, "Facebook", R.id.nav_facebook, R.color.facebook),
    UPLOADPLAN(FirebaseRepository.class, "Uploadplan", R.id.nav_upload_plan, R.color.pietsmiet),
    NEWS(FirebaseRepository.class, "PS.de News", R.id.nav_ps_news, R.color.pietsmiet);
    public final String name;
    public final Class<? extends MainRepository> aClass;
    public final int drawerId;
    public final int colorId;

    public static PostType getByDrawerId(int did) {
        for (PostType p: values()) {
            if(p.drawerId == did) return p;
        }
        return null;
    }

    /***
     * Creates a PostType.
     * @param aClass The Class Object
     * @param name The name
     * @param drawerId Resource drawer id
     * @param colorId Resource color id
     */
    PostType(Class<? extends MainRepository> aClass, String name, int drawerId, int colorId) {
        this.aClass = aClass;
        this.name = name;
        this.drawerId = drawerId;
        this.colorId = colorId;
    }
} public static boolean boolCategoryPietcast;
 public static boolean boolCategoryPietsmietNews;
 public static boolean boolCategoryPietsmietUploadplan;
 public static boolean boolCategoryPietsmietVideos;

import java.util.Date;
import java.util.Map;
import de.pscom.pietsmiet.R;
import de.pscom.pietsmiet.generic.Post;
import de.pscom.pietsmiet.json_model.firebaseApi.FirebaseApiInterface;
import de.pscom.pietsmiet.json_model.firebaseApi.FirebaseItem;
import de.pscom.pietsmiet.util.PsLog;
import de.pscom.pietsmiet.util.RetrofitHelper;
import de.pscom.pietsmiet.util.SettingsHelper;
import de.pscom.pietsmiet.view.MainActivity;
import retrofit2.Retrofit;
import rx.Observable;
import rx.schedulers.Schedulers;
import static de.pscom.pietsmiet.generic.Post.PostType;
import static de.pscom.pietsmiet.generic.Post.PostType.NEWS;
import static de.pscom.pietsmiet.generic.Post.PostType.PIETCAST;
import static de.pscom.pietsmiet.generic.Post.PostType.PS_VIDEO;
import static de.pscom.pietsmiet.generic.Post.PostType.UPLOADPLAN;
import static de.pscom.pietsmiet.util.FirebaseUtil.TOPIC_NEWS;
import static de.pscom.pietsmiet.util.FirebaseUtil.TOPIC_PIETCAST;
import static de.pscom.pietsmiet.util.FirebaseUtil.TOPIC_UPLOADPLAN;
import static de.pscom.pietsmiet.util.FirebaseUtil.TOPIC_VIDEO;
import static de.pscom.pietsmiet.util.SettingsHelper.boolCategoryPietcast;
import static de.pscom.pietsmiet.util.SettingsHelper.boolCategoryPietsmietNews;
import static de.pscom.pietsmiet.util.SettingsHelper.boolCategoryPietsmietUploadplan;
import static de.pscom.pietsmiet.util.SettingsHelper.boolCategoryPietsmietVideos;
package de.pscom.pietsmiet.repository;




public class FirebaseRepository extends MainRepository {
    FirebaseApiInterface apiInterface;

    FirebaseRepository(MainActivity view) {
        super(view);
        Retrofit retrofit = RetrofitHelper.getRetrofit(SettingsHelper.stringFirebaseDbUrl);
        apiInterface = retrofit.create(FirebaseApiInterface.class);
    }

    private Observable<Post.PostBuilder> parsePostsFromDb(Observable<Map<String, FirebaseItem>> obs) {
        return Observable.defer(() -> obs)
                .onErrorReturn(err -> {
                    PsLog.e("Couldn't load Firebase", err);
                    view.showMessage(view.getString(R.string.error_firebase_loading));
                    return null;
                })
                .filter(result -> result != null)
                .flatMapIterable(Map::values)
                .map(item -> {
                    PostType type;
                    switch (item.scope) {
                        case TOPIC_UPLOADPLAN:
                            type = UPLOADPLAN;
                            break;
                        case TOPIC_NEWS:
                            type = NEWS;
                            break;
                        case TOPIC_PIETCAST:
                            type = PIETCAST;
                            break;
                        case TOPIC_VIDEO:
                            type = PS_VIDEO;
                            break;
                        default:
                            type = null;
                    }
                    Post.PostBuilder postBuilder = new Post.PostBuilder(type);
                    if (!boolCategoryPietsmietVideos && type == PS_VIDEO) {
                        return postBuilder.empty();
                    } else if (!boolCategoryPietsmietUploadplan && type == UPLOADPLAN) {