public abstract class BenihActivity extends RxAppCompatActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(getActivityView());
        ButterKnife.bind(this);
        Timber.tag(getClass().getSimpleName());
        onViewReady(savedInstanceState);
    }

    protected abstract int getActivityView();

    protected abstract void onViewReady(Bundle savedInstanceState);
} public abstract class BenihFragment<Data extends Parcelable> extends RxFragment
{
    protected Data data;

    public BenihFragment()
    {

    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        Timber.tag(getClass().getSimpleName());
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View view = LayoutInflater.from(getActivity()).inflate(getFragmentView(), container, false);
        ButterKnife.bind(this, view);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState)
    {
        super.onActivityCreated(savedInstanceState);
        if (savedInstanceState != null)
        {
            data = savedInstanceState.getParcelable("data");
        }
        onViewReady(savedInstanceState);
    }

    public void setData(Data data)
    {
        this.data = data;
    }

    public Data getData()
    {
        return data;
    }

    protected abstract int getFragmentView();

    protected abstract void onViewReady(@Nullable Bundle savedInstanceState);

    @Override
    public void onSaveInstanceState(Bundle outState)
    {
        outState.putParcelable("data", data);
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onDestroy()
    {
        data = null;
        super.onDestroy();
    }

    public void replace(int containerId, BenihFragment fragment, boolean addToBackStack)
    {
        if (addToBackStack)
        {
            getFragmentManager().beginTransaction()
                    .replace(containerId, fragment, fragment.getClass().getSimpleName())
                    .addToBackStack(null)
                    .commit();
        } else
        {
            getFragmentManager().beginTransaction()
                    .replace(containerId, fragment, fragment.getClass().getSimpleName())
                    .commit();
        }
    }

    public void replace(int containerId, BenihFragment fragment, boolean addToBackStack, int transitionStyle)
    {
        if (addToBackStack)
        {
            getFragmentManager().beginTransaction()
                    .replace(containerId, fragment, fragment.getClass().getSimpleName())
                    .setTransitionStyle(transitionStyle)
                    .commit();
        } else
        {
            getFragmentManager().beginTransaction()
                    .replace(containerId, fragment, fragment.getClass().getSimpleName())
                    .setTransitionStyle(transitionStyle)
                    .commit();
        }
    }

    protected ActionBar getSupportActionBar()
    {
        return ((BenihActivity) getActivity()).getSupportActionBar();
    }

    protected void setSupportActionBar(Toolbar toolbar)
    {
        ((BenihActivity) getActivity()).setSupportActionBar(toolbar);
    }
} public enum BenihWorker
{
    HARVEST;

    public static BenihWorker pluck()
    {
        return HARVEST;
    }

    public Observable<Object> doInComputation(final Runnable runnable)
    {
        return Observable.create(new Observable.OnSubscribe<Object>()
        {
            @Override
            public void call(Subscriber<? super Object> subscriber)
            {
                runnable.run();
                if (!subscriber.isUnsubscribed())
                {
                    subscriber.onNext("We are done bro!");
                }
            }
        }).compose(BenihScheduler.pluck().applySchedulers(BenihScheduler.Type.COMPUTATION));
    }

    public Observable<Object> doInIO(final Runnable runnable)
    {
        return Observable.create(new Observable.OnSubscribe<Object>()
        {
            @Override
            public void call(Subscriber<? super Object> subscriber)
            {
                runnable.run();
                if (!subscriber.isUnsubscribed())
                {
                    subscriber.onNext("We are done bro!");
                }
            }
        }).compose(BenihScheduler.pluck().applySchedulers(BenihScheduler.Type.IO));
    }

    public Observable<Object> doInNewThread(final Runnable runnable)
    {
        return Observable.create(new Observable.OnSubscribe<Object>()
        {
            @Override
            public void call(Subscriber<? super Object> subscriber)
            {
                runnable.run();
                if (!subscriber.isUnsubscribed())
                {
                    subscriber.onNext("We are done bro!");
                }
            }
        }).compose(BenihScheduler.pluck().applySchedulers(BenihScheduler.Type.NEW_THREAD));
    }
} public class BookmarkController extends BenihController<BookmarkController.Presenter>
{
    private List<Article> articles;
    private Article article;

    public BookmarkController(Presenter presenter)
    {
        super(presenter);
        BenihBus.pluck()
                .receive()
                .subscribe(o -> {
                    if (o instanceof BookmarkEvent)
                    {
                        onBookmarkEvent((BookmarkEvent) o);
                    }
                }, throwable -> Timber.e(throwable.getMessage()));
    }

    public void setArticle(Article article)
    {
        this.article = article;
    }

    private void onBookmarkEvent(BookmarkEvent bookmarkEvent)
    {
        if (article != null && article.getId() == bookmarkEvent.getArticle().getId())
        {
            if (bookmarkEvent.getArticle().isBookmarked() && !article.isBookmarked())
            {
                article.setBookmarked(true);
                presenter.onBookmark(article);
            } else if (!bookmarkEvent.getArticle().isBookmarked() && article.isBookmarked())
            {
                article.setBookmarked(false);
                presenter.onUnBookmark(article);
            }
        }
    }

    public void loadBookmarkedArticles()
    {
        presenter.showLoading();
        DataBaseHelper.pluck()
                .getBookmarkedArticles()
                .compose(BenihScheduler.pluck().applySchedulers(BenihScheduler.Type.IO))
                .subscribe(articles -> {
                    int size = articles.size();
                    for (int i = 0; i < size; i++)
                    {
                        articles.get(i).setBookmarked(DataBaseHelper.pluck().isBookmarked(articles.get(i).getId()));
                        articles.get(i).setReadLater(DataBaseHelper.pluck().isReadLater(articles.get(i).getId()));
                        articles.get(i).setBig(BenihUtils.randInt(0, 8) == 5);
                    }
                    this.articles = articles;
                    if (presenter != null)
                    {
                        presenter.showListBookmarkedArticles(articles);
                        presenter.dismissLoading();
                    }
                }, throwable -> {
                    if (presenter != null)
                    {
                        Timber.d(throwable.getMessage());
                        presenter.showError(new Throwable(ErrorEvent.LOAD_BOOKMARKED_ARTICLES));
                        presenter.dismissLoading();
                    }
                });
    }

    public void bookmark(Article article)
    {
        if (!article.isBookmarked())
        {
            article.setBookmarked(true);
            DataBaseHelper.pluck().bookmark(article);
            presenter.onBookmark(article);
        } else
        {
            article.setBookmarked(false);
            DataBaseHelper.pluck().unBookmark(article.getId());
            presenter.onUnBookmark(article);
        }

        BenihBus.pluck().send(new BookmarkEvent(article));
    }

    public void filter(String query)
    {
        if (articles != null)
        {
            Observable.from(articles)
                    .compose(BenihScheduler.pluck().applySchedulers(BenihScheduler.Type.NEW_THREAD))
                    .filter(article -> article.getTitle().toLowerCase().contains(query.toLowerCase()))
                    .map(article -> {
                        article.setBookmarked(DataBaseHelper.pluck().isBookmarked(article.getId()));
                        article.setReadLater(DataBaseHelper.pluck().isReadLater(article.getId()));
                        return article;
                    })
                    .toList()
                    .subscribe(presenter::showFilteredArticles, presenter::showError);
        } else
        {
            presenter.showFilteredArticles(new ArrayList<>());
        }
    }

    @Override
    public void saveState(Bundle bundle)
    {

    }

    @Override
    public void loadState(Bundle bundle)
    {

    }

    public interface Presenter extends BenihController.Presenter
    {
        void showListBookmarkedArticles(List<Article> listArticle);

        void onBookmark(Article article);

        void onUnBookmark(Article article);

        void showFilteredArticles(List<Article> articles);
    }
} public class ReadLaterController extends BenihController<ReadLaterController.Presenter>
{
    private List<Article> articles;
    private Article article;

    public ReadLaterController(Presenter presenter)
    {
        super(presenter);
        BenihBus.pluck()
                .receive()
                .subscribe(o -> {
                    if (o instanceof ReadLaterEvent)
                    {
                        onReadLaterEvent((ReadLaterEvent) o);
                    }
                }, throwable -> Timber.e(throwable.getMessage()));
    }

    public void setArticle(Article article)
    {
        this.article = article;
    }

    private void onReadLaterEvent(ReadLaterEvent readLaterEvent)
    {
        if (article != null && article.getId() == readLaterEvent.getArticle().getId())
        {
            if (readLaterEvent.getArticle().isReadLater() && !article.isReadLater())
            {
                article.setReadLater(true);
                presenter.onReadLater(article);
            } else if (!readLaterEvent.getArticle().isReadLater() && article.isReadLater())
            {
                article.setReadLater(false);
                presenter.onUnReadLater(article);
            }
        }
    }

    public void loadReadLaterArticles()
    {
        presenter.showLoading();
        DataBaseHelper.pluck()
                .getReadLaterArticles()
                .compose(BenihScheduler.pluck().applySchedulers(BenihScheduler.Type.IO))
                .subscribe(articles -> {
                    int size = articles.size();
                    for (int i = 0; i < size; i++)
                    {
                        articles.get(i).setBookmarked(DataBaseHelper.pluck().isBookmarked(articles.get(i).getId()));
                        articles.get(i).setReadLater(DataBaseHelper.pluck().isReadLater(articles.get(i).getId()));
                        articles.get(i).setBig(BenihUtils.randInt(0, 8) == 5);
                    }
                    this.articles = articles;
                    if (presenter != null)
                    {
                        presenter.showListReadLaterArticles(articles);
                        presenter.dismissLoading();
                    }
                }, throwable -> {
                    if (presenter != null)
                    {
                        Timber.d(throwable.getMessage());
                        presenter.showError(new Throwable(ErrorEvent.LOAD_READ_LATER_ARTICLES));
                        presenter.dismissLoading();
                    }
                });
    }

    public void readLater(Article article)
    {
        if (!article.isReadLater())
        {
            if (article.getContent() == null)
            {
                CodePolitanApi.pluck()
                        .getApi()
                        .getDetailArticle(article.getId())
                        .compose(BenihScheduler.pluck().applySchedulers(BenihScheduler.Type.IO))
                        .subscribe(articleObjectResponse -> DataBaseHelper.pluck().readLater(articleObjectResponse.getResult()),
                                   throwable -> {
                                       if (presenter != null)
                                       {
                                           article.setReadLater(false);
                                           Timber.d(throwable.getMessage());
                                           presenter.showError(new Throwable(ErrorEvent.ON_READ_LATER));
                                           presenter.onUnReadLater(article);
                                           BenihBus.pluck().send(new ReadLaterEvent(article));
                                       }
                                   });
            } else
            {
                DataBaseHelper.pluck().readLater(article);
            }
            article.setReadLater(true);
            presenter.onReadLater(article);
        } else
        {
            article.setReadLater(false);
            DataBaseHelper.pluck().unReadLater(article.getId());
            presenter.onUnReadLater(article);
        }

        BenihBus.pluck().send(new ReadLaterEvent(article));
    }

    public void filter(String query)
    {
        if (articles != null)
        {
            Observable.from(articles)
                    .compose(BenihScheduler.pluck().applySchedulers(BenihScheduler.Type.NEW_THREAD))
                    .filter(article -> article.getTitle().toLowerCase().contains(query.toLowerCase()))
                    .map(article -> {
                        article.setBookmarked(DataBaseHelper.pluck().isBookmarked(article.getId()));
                        article.setReadLater(DataBaseHelper.pluck().isReadLater(article.getId()));
                        return article;
                    })
                    .toList()
                    .subscribe(presenter::showFilteredArticles, presenter::showError);
        } else
        {
            presenter.showFilteredArticles(new ArrayList<>());
        }
    }

    @Override
    public void saveState(Bundle bundle)
    {

    }

    @Override
    public void loadState(Bundle bundle)
    {

    }

    public interface Presenter extends BenihController.Presenter
    {
        void showListReadLaterArticles(List<Article> listArticle);

        void onReadLater(Article article);

        void onUnReadLater(Article article);

        void showFilteredArticles(List<Article> articles);
    }
} public class Article implements Parcelable
{
    public final static String TYPE_NEWS = "news";
    public final static String TYPE_KOMIK = "nyankomik";
    public final static String TYPE_MEME = "meme";
    public final static String TYPE_QUOTE = "quotes";

    private int id;
    private String slug;
    private String title;
    private String excerpt;
    private String content;
    private String date;
    private String dateClear;
    private String link;
    private String thumbnailSmall;
    private String thumbnailMedium;
    private boolean bookmarked;
    private boolean readLater;
    private boolean big;
    private String postType;
    private List<Category> category;
    private List<Tag> tags;

    public Article()
    {
        postType = TYPE_NEWS;
    }

    protected Article(Parcel in)
    {
        id = in.readInt();
        slug = in.readString();
        title = in.readString();
        excerpt = in.readString();
        content = in.readString();
        date = in.readString();
        dateClear = in.readString();
        link = in.readString();
        thumbnailSmall = in.readString();
        thumbnailMedium = in.readString();
        bookmarked = in.readByte() != 0;
        readLater = in.readByte() != 0;
        big = in.readByte() != 0;
        postType = in.readString();
        category = in.createTypedArrayList(Category.CREATOR);
        tags = in.createTypedArrayList(Tag.CREATOR);
    }

    public static final Creator<Article> CREATOR = new Creator<Article>()
    {
        @Override
        public Article createFromParcel(Parcel in)
        {
            return new Article(in);
        }

        @Override
        public Article[] newArray(int size)
        {
            return new Article[size];
        }
    };

    public int getId()
    {
        return id;
    }

    public void setId(int id)
    {
        this.id = id;
    }

    public String getSlug()
    {
        return slug;
    }

    public void setSlug(String slug)
    {
        this.slug = slug;
    }

    public String getTitle()
    {
        return title;
    }

    public void setTitle(String title)
    {
        this.title = title;
    }

    public String getExcerpt()
    {
        return excerpt;
    }

    public void setExcerpt(String excerpt)
    {
        this.excerpt = excerpt;
    }

    public String getContent()
    {
        return content;
    }

    public void setContent(String content)
    {
        this.content = content;
    }

    public String getDate()
    {
        return date;
    }

    public void setDate(String date)
    {
        this.date = date;
    }

    public String getDateClear()
    {
        return dateClear;
    }

    public void setDateClear(String dateClear)
    {
        this.dateClear = dateClear;
    }

    public String getLink()
    {
        return link;
    }

    public void setLink(String link)
    {
        this.link = link;
    }

    public String getThumbnailSmall()
    {
        return thumbnailSmall;
    }

    public void setThumbnailSmall(String thumbnailSmall)
    {
        this.thumbnailSmall = thumbnailSmall;
    }

    public String getThumbnailMedium()
    {
        return thumbnailMedium;
    }

    public void setThumbnailMedium(String thumbnailMedium)
    {
        this.thumbnailMedium = thumbnailMedium;
    }

    public boolean isBookmarked()
    {
        return bookmarked;
    }

    public void setBookmarked(boolean bookmarked)
    {
        this.bookmarked = bookmarked;
    }

    public boolean isReadLater()
    {
        return readLater;
    }

    public void setReadLater(boolean readLater)
    {
        this.readLater = readLater;
    }

    public boolean isBig()
    {
        return big;
    }

    public void setBig(boolean big)
    {
        this.big = big;
    }

    public String getPostType()
    {
        return postType;
    }

    public void setPostType(String postType)
    {
        this.postType = postType;
    }

    public List<Category> getCategory()
    {
        return category;
    }

    public void setCategory(List<Category> category)
    {
        this.category = category;
    }

    public List<Tag> getTags()
    {
        return tags;
    }

    public void setTags(List<Tag> tags)
    {
        this.tags = tags;
    }

    @Override
    public int describeContents()
    {
        return hashCode();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags)
    {
        dest.writeInt(id);
        dest.writeString(slug);
        dest.writeString(title);
        dest.writeString(excerpt);
        dest.writeString(content);
        dest.writeString(date);
        dest.writeString(dateClear);
        dest.writeString(link);
        dest.writeString(thumbnailSmall);
        dest.writeString(thumbnailMedium);
        dest.writeByte((byte) (bookmarked ? 1 : 0));
        dest.writeByte((byte) (readLater ? 1 : 0));
        dest.writeByte((byte) (big ? 1 : 0));
        dest.writeString(postType);
        dest.writeTypedList(category);
        dest.writeTypedList(tags);
    }
} public class LocalDataManager
{
    public static void saveArticles(List<Article> articles)
    {
        BenihPreferenceUtils.putString(CodePolitanApplication.pluck().getApplicationContext(), "articles",
                                       Bson.pluck().getParser().toJson(articles));
    }

    public static void savePosition(int position)
    {
        BenihPreferenceUtils.putInt(CodePolitanApplication.pluck().getApplicationContext(), "position", position);
    }

    public static List<Article> getArticles()
    {
        return Bson.pluck()
                .getParser()
                .fromJson(BenihPreferenceUtils.getString(CodePolitanApplication.pluck().getApplicationContext(), "articles"),
                          new TypeToken<List<Article>>() {}.getType());
    }

    public static int getPosition()
    {
        return BenihPreferenceUtils.getInt(CodePolitanApplication.pluck().getApplicationContext(), "position");
    }

    public static void setFollowAll(boolean isFollowAll)
    {
        BenihPreferenceUtils.putBoolean(CodePolitanApplication.pluck().getApplicationContext(),
                                        "follow_all_categories", isFollowAll);
    }

    public static boolean isFollowAll()
    {
        return BenihPreferenceUtils.getBoolean(CodePolitanApplication.pluck().getApplicationContext(),
                                               "follow_all_categories");
    }

    public static void setNotificationActive(boolean isNotificationActive)
    {
        BenihPreferenceUtils.putBoolean(CodePolitanApplication.pluck().getApplicationContext(),
                                        "notification", isNotificationActive);
    }

    public static boolean isNotificationActive()
    {
        return BenihPreferenceUtils.getBoolean(CodePolitanApplication.pluck().getApplicationContext(),
                                               "notification");
    }

    public static void setRingtone(String path)
    {
        BenihPreferenceUtils.putString(CodePolitanApplication.pluck().getApplicationContext(),
                                       "ringtone", path);
    }

    public static String getRingtone()
    {
        return BenihPreferenceUtils.getString(CodePolitanApplication.pluck().getApplicationContext(),
                                              "ringtone");
    }

    public static void setVibrate(boolean isVibrate)
    {
        BenihPreferenceUtils.putBoolean(CodePolitanApplication.pluck().getApplicationContext(),
                                        "vibrate", isVibrate);
    }

    public static boolean isVibrate()
    {
        return BenihPreferenceUtils.getBoolean(CodePolitanApplication.pluck().getApplicationContext(),
                                               "vibrate");
    }

    public static void setAutoRemoveReadLater(boolean isAutoRemove)
    {
        BenihPreferenceUtils.putBoolean(CodePolitanApplication.pluck().getApplicationContext(),
                                        "remove_read_later", isAutoRemove);
    }

    public static boolean isAutoRemoveReadLater()
    {
        Context context = CodePolitanApplication.pluck().getApplicationContext();
        SharedPreferences sharedPreferences = context.getSharedPreferences("Zelory", Context.MODE_PRIVATE);
        return sharedPreferences.getBoolean("remove_read_later", true);
    }
} public class MenuShareAdapter extends BaseAdapter
{
    private LayoutInflater layoutInflater;

    public MenuShareAdapter(Context context)
    {
        layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount()
    {
        return 8;
    }

    @Override
    public Object getItem(int position)
    {
        return position;
    }

    @Override
    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        ViewHolder viewHolder;
        View view = convertView;
        if (view == null)
        {
            view = layoutInflater.inflate(R.layout.menu_item_share, parent, false);
            viewHolder = new ViewHolder();
            viewHolder.textView = (TextView) view.findViewById(R.id.text_view);
            viewHolder.imageView = (ImageView) view.findViewById(R.id.image_view);
            view.setTag(viewHolder);

        } else
        {
            viewHolder = (ViewHolder) view.getTag();
        }

        switch (position)
        {
            case 0:
                viewHolder.textView.setText("Google Plus");
                viewHolder.imageView.setImageResource(R.drawable.ic_google_plus);
                break;
            case 1:
                viewHolder.textView.setText("Email");
                viewHolder.imageView.setImageResource(R.drawable.ic_gmail);
                break;
            case 2:
                viewHolder.textView.setText("Messenger");
                viewHolder.imageView.setImageResource(R.drawable.ic_massanger);
                break;
            case 3:
                viewHolder.textView.setText("WhatsApp");
                viewHolder.imageView.setImageResource(R.drawable.ic_whatsapp);
                break;
            case 4:
                viewHolder.textView.setText("Messaging");
                viewHolder.imageView.setImageResource(R.drawable.ic_messaging);
                break;
            case 5:
                viewHolder.textView.setText("Facebook");
                viewHolder.imageView.setImageResource(R.drawable.ic_fb);
                break;
            case 6:
                viewHolder.textView.setText("Twitter");
                viewHolder.imageView.setImageResource(R.drawable.ic_twitter);
                break;
            case 7:
                viewHolder.textView.setText("More");
                viewHolder.imageView.setImageResource(R.drawable.ic_more);
                break;
        }

        return view;
    }

    private static class ViewHolder
    {
        TextView textView;
        ImageView imageView;
    }

} public class ReadPagerAdapter extends BenihPagerAdapter<BenihFragment>
{
    public ReadPagerAdapter(FragmentManager fm, List<BenihFragment> readFragments)
    {
        super(fm, readFragments);
    }

    @Override
    public BenihFragment getItem(int i)
    {
        return fragments.get(i);
    }
} public class ImageReadFragment extends BenihFragment<Article> implements
        ArticleController.Presenter, Animation.AnimationListener
{
    private ArticleController controller;
    private Animation fadein, fadeout;
    @Bind(R.id.image) TouchImageView image;
    @Bind(R.id.title) TextView title;
    @Bind(R.id.ll_tags) LinearLayout llTags;
    @Bind(R.id.ll_footer) LinearLayout footer;
    @Bind(R.id.progress_bar) ProgressBar progressBar;

    @Override
    protected int getFragmentView()
    {
        return R.layout.fragment_image_read;
    }

    @Override
    protected void onViewReady(@Nullable Bundle savedInstanceState)
    {
        fadein = AnimationUtils.loadAnimation(getActivity(), R.anim.fadein);
        fadein.setAnimationListener(this);
        fadeout = AnimationUtils.loadAnimation(getActivity(), R.anim.fadeout);
        fadeout.setAnimationListener(this);
        hideTitle();
        setUpController(savedInstanceState);
    }

    private void setUpController(Bundle savedInstanceState)
    {
        if (controller == null)
        {
            controller = new ArticleController(this);
        }

        if (savedInstanceState != null)
        {
            controller.loadState(savedInstanceState);
        } else if (data.getContent() != null)
        {
            showArticle(data);
            controller.setArticle(data);
        } else
        {
            new Handler().postDelayed(() -> {
                if (data != null)
                {
                    controller.loadArticle(data.getId());
                }
            }, 800);
        }
    }

    @Override
    public void showArticle(Article article)
    {
        title.setText(article.getTitle());

        Glide.with(this)
                .load(ArticleUtil.getFullImage(article))
                .listener(new RequestListener<String, GlideDrawable>()
                {
                    @Override
                    public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource)
                    {
                        image.setImageResource(R.drawable.could_not_load_image_big);
                        progressBar.setVisibility(View.GONE);
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource)
                    {
                        progressBar.setVisibility(View.GONE);
                        return false;
                    }
                })
                .into(image);

        image.setOnClickListener(v -> showTitle());
        llTags.removeAllViews();
        int size = article.getTags().size();
        for (int i = 0; i < size; i++)
        {
            TextView tag = (TextView) LayoutInflater.from(getActivity()).inflate(R.layout.item_tag_read, llTags, false);
            tag.setText(String.format("# %s", article.getTags().get(i).getName()));
            final int position = i;
            tag.setOnClickListener(v -> onTagClick(article.getTags().get(position)));
            llTags.addView(tag);
        }
    }

    private void showTitle()
    {
        footer.startAnimation(fadein);
        hideTitle();
    }

    private void hideTitle()
    {
        new Handler().postDelayed(() -> footer.startAnimation(fadeout), 3000);
    }

    private void onTagClick(Tag tag)
    {
        Intent intent = new Intent(getActivity(), ListArticleActivity.class);
        intent.putExtra(ListArticleActivity.KEY_TYPE, ListArticleActivity.TYPE_TAG);
        intent.putExtra(ListArticleActivity.KEY_DATA, tag);
        startActivity(intent);
    }

    @Override
    public void showArticles(List<Article> articles)
    {

    }

    @Override
    public void showFilteredArticles(List<Article> articles)
    {

    }

    @Override
    public void showError(Throwable throwable)
    {
        switch (throwable.getMessage())
        {
            case ErrorEvent.LOAD_STATE_ARTICLE:
                controller.loadArticle(data.getId());
                break;
            case ErrorEvent.LOAD_ARTICLE:
                Toast.makeText(getActivity(), getString(R.string.error_message), Toast.LENGTH_LONG).show();
                break;
        }
    }

    @Override
    public void showLoading()
    {
        progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void dismissLoading()
    {
    }

    @Override
    public void onSaveInstanceState(Bundle outState)
    {
        controller.saveState(outState);
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onAnimationStart(Animation animation)
    {

    }

    @Override
    public void onAnimationEnd(Animation animation)
    {
        footer.setVisibility(animation == fadein ? View.VISIBLE : View.INVISIBLE);
    }

    @Override
    public void onAnimationRepeat(Animation animation)
    {

    }

    @OnClick(R.id.iv_refresh)
    public void onRefresh()
    {
        controller.loadArticle(data.getId());
    }
} public class ReadFragment extends BenihFragment<Article> implements ArticleController.Presenter,
        RandomContentController.Presenter, SwipeRefreshLayout.OnRefreshListener
{
    private ArticleController articleController;
    private RandomContentController randomContentController;
    private Animation animation;
    @Bind(R.id.image) CodePolitanImageView image;
    @Bind(R.id.iv_error) ImageView ivError;
    @Bind(R.id.title) TextView title;
    @Bind(R.id.date) TextView date;
    @Bind(R.id.category) TextView category;
    @Bind(R.id.content) BenihWebView content;
    @Bind(R.id.ll_tags) LinearLayout llTags;
    @Bind(R.id.ll_other_articles) LinearLayout llOtherArticles;
    @Bind(R.id.ll_root) LinearLayout llRoot;
    @Bind(R.id.swipe_layout) SwipeRefreshLayout swipeRefreshLayout;

    @Override
    protected int getFragmentView()
    {
        return R.layout.fragment_read;
    }

    @Override
    protected void onViewReady(Bundle bundle)
    {
        animation = AnimationUtils.loadAnimation(getActivity(), R.anim.simple_grow);
        image.setBackgroundColor(BenihUtils.getRandomColor());
        setupWebView();
        setupController(bundle);
        setUpSwipeLayout();
    }

    protected void setUpSwipeLayout()
    {
        swipeRefreshLayout.setColorSchemeResources(R.color.primary, R.color.accent);
        swipeRefreshLayout.setOnRefreshListener(this);
    }

    private void setupController(Bundle bundle)
    {
        if (articleController == null)
        {
            articleController = new ArticleController(this);
        }

        if (bundle != null)
        {
            articleController.loadState(bundle);
        } else if (data.getContent() != null)
        {
            showArticle(data);
            articleController.setArticle(data);
        } else
        {
            new Handler().postDelayed(() -> {
                if (data != null)
                {
                    articleController.loadArticle(data.getId());
                }
            }, 800);
        }

        if (randomContentController == null)
        {
            randomContentController = new RandomContentController(this);
        }

        if (bundle != null)
        {
            randomContentController.loadState(bundle);
        } else
        {
            new Handler().postDelayed(randomContentController::loadRandomArticles, 800);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState)
    {
        articleController.saveState(outState);
        randomContentController.saveState(outState);
        super.onSaveInstanceState(outState);
    }

    @Override
    public void showArticle(Article article)
    {
        image.setImageUrl(article.getThumbnailMedium(), ivError);
        title.setText(Html.fromHtml(article.getTitle()));
        date.setText(article.getDateClear());
        if (article.getCategory() != null && !article.getCategory().isEmpty())
        {
            category.setText(Html.fromHtml(article.getCategory().get(0).getName()));
            category.setOnClickListener(v -> onCategoryClick(article.getCategory().get(0)));
        }
        content.loadData(article.getContent());
        llTags.removeAllViews();
        int size = article.getTags().size();
        for (int i = 0; i < size; i++)
        {
            TextView tag = (TextView) LayoutInflater.from(getActivity()).inflate(R.layout.item_tag_read, llTags, false);
            tag.setText(Html.fromHtml(String.format("# %s", article.getTags().get(i).getName())));
            final int position = i;
            tag.setOnClickListener(v -> onTagClick(article.getTags().get(position)));
            llTags.addView(tag);
        }
        llRoot.setVisibility(View.VISIBLE);
        llRoot.startAnimation(animation);

        new Handler().postDelayed(() -> content.loadData(article.getContent()), 800);
    }

    private void onTagClick(Tag tag)
    {
        Intent intent = new Intent(getActivity(), ListArticleActivity.class);
        intent.putExtra(ListArticleActivity.KEY_TYPE, ListArticleActivity.TYPE_TAG);
        intent.putExtra(ListArticleActivity.KEY_DATA, tag);
        startActivity(intent);
    }

    private void onCategoryClick(Category category)
    {
        Intent intent = new Intent(getActivity(), ListArticleActivity.class);
        intent.putExtra(ListArticleActivity.KEY_TYPE, ListArticleActivity.TYPE_CATEGORY);
        intent.putExtra(ListArticleActivity.KEY_DATA, category);
        startActivity(intent);
    }

    @Override
    public void showArticles(List<Article> articles)
    {

    }

    @Override
    public void showRandomArticles(List<Article> articles)
    {
        llOtherArticles.removeAllViews();
        int size = articles.size();
        for (int i = 5; i < size; i++)
        {
            Article article = articles.get(i);
            View itemView = LayoutInflater.from(getActivity()).inflate(R.layout.list_item_news_mini, llOtherArticles, false);
            OtherArticleItemView otherArticleItemView = new OtherArticleItemView(itemView);
            otherArticleItemView.bind(article);
            final int position = i;
            otherArticleItemView.getView().setOnClickListener(v -> onOtherArticleClick(articles, position));
            llOtherArticles.addView(otherArticleItemView.getView());
        }
    }

    private void onOtherArticleClick(List<Article> articles, int position)
    {
        LocalDataManager.saveArticles(articles);
        LocalDataManager.savePosition(position);
        startActivity(new Intent(getActivity(), ReadActivity.class));
    }

    @Override
    public void showRandomCategory(Category category)
    {

    }

    @Override
    public void showRandomTag(Tag tag)
    {

    }

    @Override
    public void showFilteredArticles(List<Article> articles)
    {

    }

    @Override
    public void showLoading()
    {
        swipeRefreshLayout.setRefreshing(true);
    }

    @Override
    public void dismissLoading()
    {
        swipeRefreshLayout.setRefreshing(false);
    }

    @Override
    public void showError(Throwable throwable)
    {
        switch (throwable.getMessage())
        {
            case ErrorEvent.LOAD_STATE_ARTICLE:
                articleController.loadArticle(data.getId());
                break;
            case ErrorEvent.LOAD_ARTICLE:
                Toast.makeText(getActivity(), getString(R.string.error_message), Toast.LENGTH_LONG).show();
                break;
        }
    }

    @SuppressLint("SetJavaScriptEnabled")
    private void setupWebView()
    {
        content.setWebChromeClient(new WebChromeClient());
        content.getSettings().setJavaScriptEnabled(true);
        content.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
    }

    @Override
    public void onRefresh()
    {
        articleController.loadArticle(data.getId());
        randomContentController.loadRandomArticles();
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
        content.clearCache(true);
    }
}
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.view.Menu;
import android.view.MenuItem;
import com.orhanobut.dialogplus.DialogPlus;
import com.orhanobut.dialogplus.GridHolder;
import java.util.ArrayList;
import java.util.List;
import butterknife.Bind;
import id.zelory.benih.BenihActivity;
import id.zelory.benih.fragment.BenihFragment;
import id.zelory.benih.util.BenihWorker;
import id.zelory.codepolitan.R;
import id.zelory.codepolitan.controller.BookmarkController;
import id.zelory.codepolitan.controller.ReadLaterController;
import id.zelory.codepolitan.data.model.Article;
import id.zelory.codepolitan.data.LocalDataManager;
import id.zelory.codepolitan.ui.adapter.MenuShareAdapter;
import id.zelory.codepolitan.ui.adapter.ReadPagerAdapter;
import id.zelory.codepolitan.ui.fragment.ImageReadFragment;
import id.zelory.codepolitan.ui.fragment.ReadFragment;
/*
 * Copyright (c) 2015 Zelory.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package id.zelory.codepolitan.ui;





/**
 * Created on : July 28, 2015
 * Author     : zetbaitsu
 * Name       : Zetra
 * Email      : zetra@mail.ugm.ac.id
 * GitHub     : https://github.com/zetbaitsu
 * LinkedIn   : https://id.linkedin.com/in/zetbaitsu
 */
public class ReadActivity extends BenihActivity implements ViewPager.OnPageChangeListener,
        ReadLaterController.Presenter, BookmarkController.Presenter
{
    public static final String KEY_TYPE = "type";
    public static final int TYPE_FROM_NOTIF = 1;

    private ReadPagerAdapter adapter;
    private List<BenihFragment> readFragments;
    private List<Article> articles;