public class EditorActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if(!Utils.isLoggedIn())
            finish();

        EditorFragment bm = (EditorFragment) getSupportFragmentManager()
                .findFragmentByTag("editor");
        if (bm == null)
            bm = EditorFragment.newInstance(mExtras);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().add(R.id.content, bm, "editor").commit();
        }
    }

} public class MediaActivity extends BaseActivity {
    private static final String FRAGMENT_TAG = "media";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // create and add the fragment
        MediaFragment fragment = (MediaFragment) getSupportFragmentManager()
                .findFragmentByTag(FRAGMENT_TAG);
        if (fragment == null)
            fragment = MediaFragment.newInstance(mExtras);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.content, fragment, FRAGMENT_TAG)
                    .commit();
        }
    }

} public enum SwipyRefreshLayoutDirection {

    TOP(0),
    BOTTOM(1),
    BOTH(2);

    private int mValue;

    SwipyRefreshLayoutDirection(int value) {
        this.mValue = value;
    }

    public static SwipyRefreshLayoutDirection getFromInt(int value) {
        for (SwipyRefreshLayoutDirection direction : SwipyRefreshLayoutDirection.values()) {
            if (direction.mValue == value) {
                return direction;
            }
        }
        return BOTH;
    }

} public class Post implements Serializable {

    private static final long serialVersionUID = 1L;

    private Integer mId;
    private Topic mTopic;
    private Board mBoard;
    private String mText;
    private Date mDate;
    private String mTitle;
    private User mAuthor;
    private Integer mEdited;
    private User mLastEditUser;
    private Date mLastEditDate;
    private Integer mIconId;
    private String mIconFile;
    public String mBookmarktoken;
    public String mEdittoken;
    public String mQuickmodToken;
    public Boolean mIsHidden;
    public Boolean mIsTextHidden;

    public Date getLastEditDate() {
        return mLastEditDate;
    }

    public void setLastEditDate(Date mLastEditDate) {
        this.mLastEditDate = mLastEditDate;
    }

    public void setLastEditDateFromTimestamp(long timestamp) {
        this.mLastEditDate = new Date(timestamp * 1000);
    }

    public User getLastEditUser() {
        return mLastEditUser;
    }

    public void setLastEditUser(User mLastEditUser) {
        this.mLastEditUser = mLastEditUser;
    }

    public Post(Integer id) {
        mId = id;
    }

    public Post() {
    }

    public void setText(String text) {
        try {
            mText = new String(text.getBytes(), "utf-8");
        } catch (UnsupportedEncodingException e) {
            mText = text;
        }
    }

    public void setId(Integer id) {
        mId = id;
    }

    public void setTopic(Topic topic) {
        mTopic = topic;
    }

    public void setBoard(Board board) {
        mBoard = board;
    }

    public void setAuthor(User author) {
        mAuthor = author;
    }

    public void setBookmarktoken(String bookmarktoken) {
        mBookmarktoken = bookmarktoken;
    }

    public void setEdittoken(String edittoken) {
        mEdittoken = edittoken;
    }

    public void setDate(Date d) {
        mDate = d;
    }

    public void setDateFromTimestamp(long timestamp) {
        mDate = new Date(timestamp * 1000);
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    public void setIconId(Integer icon) {
        mIconId = icon;
    }

    public void setIconFile(String icon) {
        mIconFile = icon;
    }

    public Integer getId() {
        return mId;
    }

    public String getEdittoken() {
        return mEdittoken;
    }

    public Date getDate() {
        return mDate;
    }

    public String getTitle() {
        return mTitle;
    }

    public User getAuthor() {
        return mAuthor;
    }

    public String getBookmarktoken() {
        return mBookmarktoken;
    }

    public String getText() {
        return mText;
    }

    public Integer getIconId() {
        return mIconId;
    }

    public String getIconFile() {
        return mIconFile;
    }

    public Topic getTopic() {
        return mTopic;
    }

    public Board getBoard() {
        return mBoard;
    }

    public void setEdited(Integer ed) {
        mEdited = ed;
    }

    public Integer getEdited() {
        return mEdited;
    }

    public void setQuickmodToken(String token) {
        mQuickmodToken = token;
    }

    public String getQuickmodToken() {
        return mQuickmodToken;
    }

    public boolean isHidden() {
        return mIsHidden;
    }

    public void setIsHidden(Boolean isHidden) {
        mIsHidden = isHidden;
    }

    public boolean isTextHidden() {
        return mIsTextHidden;
    }

    public void setIsTextHidden(Boolean isHidden) {
        mIsTextHidden = isHidden;
    }
} public class Topic implements Serializable {

    private static final long serialVersionUID = 2L;

    private Integer mId;
    private Integer mNumberOfPosts;
    private Integer mNumberOfHits;
    private Integer mNumberOfPages;
    private Integer mPage;
    private Integer mOffset;
    private Integer mPid;
    private Integer mPostsPerPage = 30;
    private String mTitle;
    private String mSubTitle;
    private Board mBoard;
    private User mAuthor;
    private Boolean mIsImportant;
    private Boolean mIsClosed;
    private Boolean mIsHidden = false;
    private Boolean mIsAnnouncement;
    private Boolean mIsGlobal;
    private Boolean mIsSticky;
    private Boolean mCanClose;
    private Boolean mCanHide;
    private Boolean mCanSticky;
    private Boolean mCanHidePost;
    private String mNewreplytoken;
    private String mQuickmodToken;
    private Integer mLastFetchedPage;
    private Post mFirstPost;
    private Post mLastPost;
    private ArrayList<Post> mPosts = new ArrayList<Post>();
    private String mHtmlCache;
    private Boolean mIsCacheOnly;
    private ArrayList<String> mMedia = new ArrayList<>();

    public Boolean getIsCacheOnly() {
        return mIsCacheOnly;
    }

    public void setIsCacheOnly(Boolean isCacheOnly) {
        this.mIsCacheOnly = isCacheOnly;
    }

    // constructor for TopicActivity
    public Topic(Integer id) {
        mId = id;
    }

    public Topic() {
    }

    public void setId(int id) {
        mId = id;
    }

    public Integer getNumberOfPosts() {
        return mNumberOfPosts;
    }

    public void setNumberOfPosts(Integer numberOfPosts) {
        mNumberOfPosts = numberOfPosts + 1;
    }

    public void setNumberOfPages(Integer numberOfPages) {
        mNumberOfPages = numberOfPages;
    }

    public Integer getNumberOfHits() {
        return mNumberOfHits;
    }

    public void setNumberOfHits(Integer numberOfHits) {
        mNumberOfHits = numberOfHits;
    }

    public Integer getNumberOfPages() {
        if (mNumberOfPages == null)
            mNumberOfPages = (mNumberOfPosts - 1) / mPostsPerPage + 1;
        return mNumberOfPages;
    }

    public Integer getPage() {
        return mPage;
    }

    public void setPage(Integer page) {
        mPage = page;
    }

    public Integer getOffset() {
        return mOffset;
    }

    public void setOffset(Integer offset) {
        mOffset = offset;
    }

    public Integer getPid() {
        return mPid;
    }

    public void setPid(Integer pid) {
        mPid = pid;
    }

    public Integer getPostsPerPage() {
        return mPostsPerPage;
    }

    public void setFirstPost(Post post) {
        mFirstPost = post;
    }

    public Post getFirstPost() {
        return mFirstPost;
    }

    public void setLastPost(Post post) {
        mLastPost = post;
    }

    public Post getLastPost() {
        return mLastPost;
    }
    

    public Integer getIconId() {
        return mFirstPost.getIconId();
    }

    public String getIconFile() {
        return mFirstPost.getIconFile();
    }

    public void setPostsPerPage(Integer postsPerPage) {
        mPostsPerPage = postsPerPage;
    }

    public Integer getLastFetchedPage() {
        return mLastFetchedPage;
    }

    public void setLastFetchedPage(Integer lastFetchedPage) {
        mLastFetchedPage = lastFetchedPage;
    }

    public String getTitle() {
        return mTitle;
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    public String getSubTitle() {
        return mSubTitle;
    }

    public void setSubTitle(String subTitle) {
        mSubTitle = subTitle;
    }

    public Board getBoard() {
        return mBoard;
    }

    public void setBoard(Board board) {
        mBoard = board;
    }

    public User getAuthor() {
        return mAuthor;
    }

    public void setAuthor(User author) {
        mAuthor = author;
    }

    public Boolean isImportant() {
        return mIsImportant;
    }

    public void setIsImportant(Boolean isImportant) {
        mIsImportant = isImportant;
    }

    public boolean isClosed() {
        return mIsClosed;
    }

    public void setIsClosed(Boolean isClosed) {
        mIsClosed = isClosed;
    }

    public boolean isHidden() {
        return mIsHidden;
    }

    public void setIsHidden(Boolean isHidden) {
        mIsHidden = isHidden;
    }

    public Boolean isAnnouncement() {
        return mIsAnnouncement;
    }

    public void setIsAnnouncement(Boolean isAnnouncement) {
        mIsAnnouncement = isAnnouncement;
    }

    public Boolean isGlobal() {
        return mIsGlobal;
    }

    public void setIsGlobal(Boolean isGlobal) {
        mIsGlobal = isGlobal;
    }

    public Boolean isSticky() {
        return mIsSticky;
    }

    public void setIsSticky(Boolean isSticky) {
        mIsSticky = isSticky;
    }

    public String getNewreplytoken() {
        return mNewreplytoken;
    }

    public void setNewreplytoken(String newreplytoken) {
        mNewreplytoken = newreplytoken;
    }

    public ArrayList<Post> getPosts() {
        return mPosts;
    }

    public void addPost(Post post) {
        mPosts.add(post);
    }

    public void setPosts(ArrayList<Post> posts) {
        mPosts = posts;
    }

    public Integer getId() {
        return mId;
    }

    public void setHtmlCache(String cache) {
        mHtmlCache = cache;
    }

    public String getHtmlCache() {
        return mHtmlCache;
    }

    public Boolean isLastPage() {
        return mPage.equals(getNumberOfPages());
    }

    public void clearMedia() {
        mMedia.clear();
    }

    public void addVideoMedia(String url) {
        mMedia.add("V"+ url);
    }

    public void addImageMedia(String url) {
        mMedia.add("I"+ url);
    }

    public void setMedia(ArrayList<String> media) {
        mMedia = media;
    }

    public ArrayList<String> getMedia() {
        return mMedia;
    }

    public Post getPostById(int id) {
        for (Post p : mPosts)
            if (p.getId() == id)
                return p;

        return null;
    }

    public Boolean canClose() {
        return mCanClose;
    }

    public void setCanClose(Boolean canClose) {
        mCanClose = canClose;
    }

    public Boolean canHide() {
        return mCanHide;
    }

    public void setCanHide(Boolean canHide) {
        mCanHide = canHide;
    }

    public Boolean canSticky() {
        return mCanSticky;
    }

    public void setCanSticky(Boolean canSticky) {
        mCanSticky = canSticky;
    }

    public Boolean canHidePost() {
        return mCanHidePost;
    }

    public void setCanHidePost(Boolean canHidePost) {
        mCanHidePost = canHidePost;
    }

    public String getQuickmodToken() {
        return mQuickmodToken;
    }

    public void setQuickmodToken(String token) {
        mQuickmodToken = token;
    }
} public class TopicParser extends DefaultHandler {

    public static String TAG = "thread";
    public static String SUBTITLE_TAG = "subtitle";
    public static String TITLE_TAG = "title";
    public static String FIRSTPOST_TAG = "firstpost";
    public static String LASTPOST_TAG = "lastpost";
    public static String ID_ATTRIBUTE = "id";
    public static String FLAGS_TAG = "flags";
    public static String POSTS_TAG = "posts";
    public static String POSTS_ATTRIBUTE_PAGE = "page";
    public static String POSTS_ATTRIBUTE_OFFSET = "offset";
    public static String IN_BOARD_TAG = "in-board";
    public static String IN_BOARD_ATTRIBUTE = "id";
    public static String NUMBER_OF_PAGES_TAG = "number-of-pages";
    public static String NUMBER_OF_PAGES_ATTRIBUTE = "value";
    public static String NUMBER_OF_HITS_TAG = "number-of-hits";
    public static String NUMBER_OF_HITS_ATTRIBUTE = "value";
    public static String NUMBER_OF_REPLIES_TAG = "number-of-replies";
    public static String NUMBER_OF_REPLIES_ATTRIBUTE = "value";
    public static String IS_CLOSED_TAG = "is-closed";
    public static String IS_CLOSED_ATTRIBUTE = "value";
    public static String IS_ANNOUNCEMENT_TAG = "is-announcement";
    public static String IS_ANNOUNCEMENT_ATTRIBUTE = "value";
    public static String IS_STICKY_TAG = "is-sticky";
    public static String IS_STICKY_ATTRIBUTE = "value";
    public static String IS_IMPORTANT_TAG = "is-important";
    public static String IS_IMPORTANT_ATTRIBUTE = "value";
    public static String IS_GLOBAL_TAG = "is-global";
    public static String IS_GLOBAL_ATTRIBUTE = "value";
    public static String IS_HIDDEN_TAG = "is-hidden";
    public static String IS_HIDDEN_ATTRIBUTE = "value";
    public static String CAN_CLOSE_TAG = "can-close";
    public static String CAN_CLOSE_ATTRIBUTE = "value";
    public static String CAN_HIDE_TAG = "can-hide";
    public static String CAN_HIDE_ATTRIBUTE = "value";
    public static String CAN_STICKY_TAG = "can-sticky";
    public static String CAN_STICKY_ATTRIBUTE = "value";
    public static String CAN_HIDE_POSTS_TAG = "can-hide-posts";
    public static String CAN_HIDE_POSTS_ATTRIBUTE = "value";
    public static String TOKEN_NEWREPLY_TAG = "token-newreply";
    public static String TOKEN_NEWREPLY_ATTRIBUTE = "value";
    public static String TOKEN_QUICKMOD_TAG = "token-quickmod";
    public static String TOKEN_QUICKMOD_ATTRIBUTE = "value";
    public static String POST_TAG = "post";
    public static String MESSAGE_TAG = "message";
    public static String ICON_TAG = "icon";
    public static String ICON_ATTRIBUTE = "id";
    public static String HIDDEN_ATTRIBUTE = "is-hidden";
    public static String MESSAGE_TITLE_TAG = "title";
    public static String MESSAGE_CONTENT_TAG = "content";
    public static String MESSAGE_EDITED_TAG = "edited";
    public static String MESSAGE_EDITED_ATTRIBUTE = "count";
    public static String MESSAGE_LASTEDIT_TAG = "lastedit";
    public static String DATE_TAG = "date";
    public static String DATE_TIMESTAMP_ATTRIBUTE = "timestamp";
    public static String IN_THREAD_TAG = "in-thread";
    public static String IN_THREAD_ID_ATTRIBUTE = "id";
    public static String TOKEN_SETBOOKMARK_TAG = "token-setbookmark";
    public static String TOKEN_SETBOOKMARK_ATTRIBUTE = "value";
    public static String TOKEN_EDITREPLY_TAG = "token-editreply";
    public static String TOKEN_EDITREPLY_ATTRIBUTE = "value";
    public static String TOKEN_POST_QUICKMOD_TAG = "token-quickmod";
    public static String TOKEN_POST_QUICKMOD_ATTRIBUTE = "value";
    public static String USER_TAG = "user";
    public static String AVATAR_TAG = "avatar";
    public static String AVATAR_ATTRIBUTE = "id";
    public static String LOCKED_ATTRIBUTE = "locked";
    public static String URL = "xml/thread.php";
    private Post mCurrentPost;
    private User mCurrentUser;
    private User mCurrentLastEditUser;
    private Topic mThread;

    public TopicParser() {
        mThread = new Topic();
    }

    public static String getUrl(int tid, int page, int pid) {
        Uri.Builder b = Uri.parse(URL).buildUpon();

        b.appendQueryParameter("update_bookmark", String.valueOf(1));
        b.appendQueryParameter("TID", String.valueOf(tid));

        if (pid > 0) {
            b.appendQueryParameter("PID", String.valueOf(pid));
        } else {
            b.appendQueryParameter("page", String.valueOf(page));
        }

        return b.build().toString();
    }

    public Topic parse(String input) {
        RootElement thread = new RootElement(TAG);

        // find the thread information
        thread.setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setId(Integer.parseInt(attributes.getValue(ID_ATTRIBUTE)));

                if (Integer.parseInt(attributes.getValue(BoardParser.CURRENT_USER_ID)) == 0) {

                    Network.logout(Utils.getApplicationContext());
                }
            }
        });
        thread.requireChild(TITLE_TAG).setEndTextElementListener(new EndTextElementListener() {

            @Override
            public void end(String body) {
                mThread.setTitle(body);
            }
        });
        thread.requireChild(SUBTITLE_TAG).setEndTextElementListener(new EndTextElementListener() {

            @Override
            public void end(String body) {
                mThread.setSubTitle(body);
            }
        });
        thread.requireChild(NUMBER_OF_HITS_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setNumberOfHits(Integer.parseInt(attributes.getValue
                        (NUMBER_OF_HITS_ATTRIBUTE)));
            }
        });
        thread.requireChild(NUMBER_OF_REPLIES_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setNumberOfPosts(Integer.parseInt(attributes.getValue
                        (NUMBER_OF_REPLIES_ATTRIBUTE)));
            }
        });
        thread.getChild(TOKEN_NEWREPLY_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setNewreplytoken(attributes.getValue(TOKEN_NEWREPLY_ATTRIBUTE));
            }
        });
        thread.getChild(TOKEN_QUICKMOD_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setQuickmodToken(attributes.getValue(TOKEN_QUICKMOD_ATTRIBUTE));
            }
        });
        thread.requireChild(IN_BOARD_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                Board b = new Board(Integer.parseInt(attributes.getValue(IN_BOARD_ATTRIBUTE)));
                mThread.setBoard(b);
            }
        });
        Element first_post = thread.getChild(FIRSTPOST_TAG).getChild(POST_TAG);
        first_post.setElementListener(new ElementListener() {

            @Override
            public void end() {
                mThread.setFirstPost(mCurrentPost);
            }

            @Override
            public void start(Attributes attributes) {
                mCurrentPost = new Post();
                mCurrentPost.setBoard(mThread.getBoard());
                mCurrentPost.setTopic(mThread);
            }
        });
        first_post.requireChild(USER_TAG).setTextElementListener(new TextElementListener() {

            @Override
            public void end(String body) {
                mCurrentUser.setNick(body);
                mCurrentPost.setAuthor(mCurrentUser);
            }

            @Override
            public void start(Attributes attributes) {
                mCurrentUser = new User(Integer.parseInt(attributes.getValue(ID_ATTRIBUTE)));
            }
        });
        first_post.requireChild(DATE_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mCurrentPost.setDateFromTimestamp(Integer.parseInt(attributes.getValue
                        (DATE_TIMESTAMP_ATTRIBUTE)));
            }
        });

        Element flags = thread.getChild(FLAGS_TAG);
        flags.requireChild(IS_CLOSED_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setIsClosed(attributes.getValue(IS_CLOSED_ATTRIBUTE).equals("1"));
            }
        });
        flags.requireChild(IS_STICKY_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setIsSticky(attributes.getValue(IS_STICKY_ATTRIBUTE).equals("1"));
            }
        });
        flags.requireChild(IS_ANNOUNCEMENT_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setIsAnnouncement(attributes.getValue(IS_ANNOUNCEMENT_ATTRIBUTE).equals
                        ("1"));
            }
        });
        flags.requireChild(IS_IMPORTANT_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setIsImportant(attributes.getValue(IS_IMPORTANT_ATTRIBUTE).equals("1"));
            }
        });
        flags.requireChild(IS_GLOBAL_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setIsGlobal(attributes.getValue(IS_GLOBAL_ATTRIBUTE).equals("1"));
            }
        });
        flags.requireChild(IS_HIDDEN_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setIsHidden(attributes.getValue(IS_HIDDEN_ATTRIBUTE).equals("1"));
            }
        });
        flags.requireChild(CAN_CLOSE_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setCanClose(attributes.getValue(CAN_CLOSE_ATTRIBUTE).equals("1"));
            }
        });
        flags.requireChild(CAN_HIDE_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setCanHide(attributes.getValue(CAN_HIDE_ATTRIBUTE).equals("1"));
            }
        });
        flags.requireChild(CAN_STICKY_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setCanSticky(attributes.getValue(CAN_STICKY_ATTRIBUTE).equals("1"));
            }
        });
        flags.requireChild(CAN_HIDE_POSTS_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setCanHidePost(attributes.getValue(CAN_HIDE_POSTS_ATTRIBUTE).equals("1"));
            }
        });

        Element posts = thread.requireChild(POSTS_TAG);
        posts.setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mThread.setPage(Integer.parseInt(attributes.getValue(POSTS_ATTRIBUTE_PAGE)));
                mThread.setOffset(Integer.parseInt(attributes.getValue(POSTS_ATTRIBUTE_OFFSET)));
            }
        });

        Element post = posts.getChild(POST_TAG);
        post.setElementListener(new ElementListener() {

            @Override
            public void end() {
                mThread.addPost(mCurrentPost);
            }

            @Override
            public void start(Attributes attributes) {
                mCurrentPost = new Post(Integer.parseInt(attributes.getValue(ID_ATTRIBUTE)));
                mCurrentPost.setBoard(mThread.getBoard());
                mCurrentPost.setTopic(mThread);
                String h = attributes.getValue(HIDDEN_ATTRIBUTE);
                mCurrentPost.setIsHidden(h != null && h.equals("hidden"));
                mCurrentPost.setIsTextHidden(h != null && h.equals("texthidden"));
            }
        });
        post.requireChild(USER_TAG).setTextElementListener(new TextElementListener() {

            @Override
            public void end(String body) {
                mCurrentUser.setNick(body);
                mCurrentPost.setAuthor(mCurrentUser);
            }

            @Override
            public void start(Attributes attributes) {
                mCurrentUser = new User(Integer.parseInt(attributes.getValue(ID_ATTRIBUTE)));
                if(attributes.getValue(LOCKED_ATTRIBUTE) != null)
                    mCurrentUser.setLocked(attributes.getValue(LOCKED_ATTRIBUTE).equals("1"));
            }
        });
        post.requireChild(DATE_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mCurrentPost.setDateFromTimestamp(Integer.parseInt(attributes.getValue
                        (DATE_TIMESTAMP_ATTRIBUTE)));
            }
        });
        post.getChild(TOKEN_SETBOOKMARK_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mCurrentPost.setBookmarktoken(attributes.getValue(TOKEN_SETBOOKMARK_ATTRIBUTE));
            }
        });
        post.getChild(TOKEN_EDITREPLY_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mCurrentPost.setEdittoken(attributes.getValue(TOKEN_EDITREPLY_ATTRIBUTE));
            }
        });
        post.getChild(TOKEN_POST_QUICKMOD_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mCurrentPost.setQuickmodToken(attributes.getValue(TOKEN_POST_QUICKMOD_ATTRIBUTE));
            }
        });
        post.requireChild(AVATAR_TAG).setTextElementListener(new TextElementListener() {

            @Override
            public void start(Attributes attributes) {
                mCurrentUser.setAvatarId(Integer.parseInt(attributes.getValue(AVATAR_ATTRIBUTE)));
            }

            @Override
            public void end(String body) {
                mCurrentUser.setAvatarFile(body);
            }
        });
        post.getChild(ICON_TAG).setTextElementListener(new TextElementListener() {

            @Override
            public void start(Attributes attributes) {
                mCurrentPost.setIconId(Integer.parseInt(attributes.getValue(ICON_ATTRIBUTE)));
            }

            @Override
            public void end(String body) {
                mCurrentPost.setIconFile(body);
            }
        });

        Element message = post.getChild(MESSAGE_TAG);
        message.requireChild(MESSAGE_CONTENT_TAG).setEndTextElementListener(new EndTextElementListener() {

            @Override
            public void end(String body) {
                mCurrentPost.setText(body);
            }
        });
        message.requireChild(MESSAGE_TITLE_TAG).setEndTextElementListener(new EndTextElementListener() {

            @Override
            public void end(String body) {
                mCurrentPost.setTitle(body);
            }
        });
        message.requireChild(MESSAGE_EDITED_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mCurrentPost.setEdited(Integer.parseInt(attributes.getValue
                        (MESSAGE_EDITED_ATTRIBUTE)));
            }
        });

        Element lastedit = message.getChild(MESSAGE_EDITED_TAG).getChild(MESSAGE_LASTEDIT_TAG);
        lastedit.getChild(USER_TAG).setTextElementListener(new TextElementListener() {

            @Override
            public void end(String body) {
                mCurrentLastEditUser.setNick(body);
                mCurrentPost.setLastEditUser(mCurrentLastEditUser);
            }

            @Override
            public void start(Attributes attributes) {
                mCurrentLastEditUser = new User(Integer.parseInt(attributes.getValue
                        (ID_ATTRIBUTE)));
                if(attributes.getValue(LOCKED_ATTRIBUTE) != null)
                    mCurrentLastEditUser.setLocked(attributes.getValue(LOCKED_ATTRIBUTE).equals("1"));
            }
        });
        lastedit.getChild(DATE_TAG).setStartElementListener(new StartElementListener() {

            @Override
            public void start(Attributes attributes) {
                mCurrentPost.setLastEditDateFromTimestamp(Integer.parseInt(attributes.getValue
                        (DATE_TIMESTAMP_ATTRIBUTE)));
            }
        });

        try {
            Xml.parse(input, thread.getContentHandler());
        } catch (SAXException e) {
            Utils.printException(e);
            return null;
        }

        return mThread;
    }
} public class ChoosePageDialog extends DialogFragment {
    public static ChoosePageDialog getInstance(int pages) {
        ChoosePageDialog f = new ChoosePageDialog();

        // Supply index input as an argument.
        Bundle args = new Bundle();
        args.putInt("pages", pages);
        f.setArguments(args);

        return f;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        CharSequence[] items = new CharSequence[getArguments().getInt("pages")];
        for(int i=0; i < items.length; ++i) {
            items[i] = "Seite "+(i+1);
        }

        return new MaterialDialog.Builder(getActivity())
                .title(R.string.action_topage)
                .adapter(new ChoosePageDialog.PageListAdapter(), new GridLayoutManager(getActivity(), 4))
                .build();
    }

    public class PageListAdapter extends RecyclerView.Adapter<ChoosePageDialog.PageListAdapter.ViewHolder> {
        private ArrayList<String> mDataset = new ArrayList<String>();

        @Override
        public ChoosePageDialog.PageListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            FrameLayout v = (FrameLayout) LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.listitem_number, parent, false);

            return new ChoosePageDialog.PageListAdapter.ViewHolder(v);
        }

        @Override
        public void onBindViewHolder(ChoosePageDialog.PageListAdapter.ViewHolder holder, final int position) {
            String icon = mDataset.get(position);

            holder.mText.setText(icon);

            holder.mRoot.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    ((TopicFragment)getTargetFragment()).goToPage(position + 1);
                    getDialog().dismiss();
                }
            });
        }

        @Override
        public int getItemCount() {
            return mDataset.size();
        }

        class ViewHolder extends RecyclerView.ViewHolder {

            FrameLayout mRoot;
            TextView mText;

            ViewHolder(FrameLayout container) {
                super(container);
                mRoot = container;
                mText = (TextView) mRoot.findViewById(R.id.name);
            }
        }

        PageListAdapter() {
            CharSequence[] items = new CharSequence[getArguments().getInt("pages")];
            for(int i=0; i < items.length; ++i) {
                mDataset.add(i, ""+(i+1));
            }
        }

    }
} public class ImageActionsDialog extends DialogFragment {

    public static final String ARG_IMAGE_URI = "image_uri";
    public static final String TAG = "imagemenu";

    public static ImageActionsDialog getInstance(Uri image_uri) {
        ImageActionsDialog f = new ImageActionsDialog();

        // Supply index input as an argument.
        Bundle args = new Bundle();
        args.putString(ARG_IMAGE_URI, image_uri.toString());
        f.setArguments(args);

        return f;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        return new MaterialDialog.Builder(getActivity())
                .items(R.array.image_dialog)
                .title(R.string.image_dialog_title)
                .itemsCallback(new MaterialDialog.ListCallback() {
                    @Override
                    public void onSelection(MaterialDialog materialDialog, View view, int i, CharSequence charSequence) {
                        final String url = getArguments().getString(ARG_IMAGE_URI);
                        final Uri uri = Uri.parse(url);
                        switch (i) {
                            case 0:
                                Intent intent = new Intent(getActivity(), MediaActivity.class);
                                if (url.endsWith("gif"))
                                    intent.putExtra(MediaFragment.ARG_TYPE, "gif");
                                else
                                    intent.putExtra(MediaFragment.ARG_TYPE, "image");
                                intent.putExtra(MediaFragment.ARG_URI, url);
                                startActivityForResult(intent, 0);
                                break;
                            case 1:
                                Intent shareIntent = new Intent();
                                shareIntent.setAction(Intent.ACTION_SEND);
                                shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
                                shareIntent.setType("image/*");
                                startActivity(Intent.createChooser(shareIntent, "Share with"));
                                break;
                            case 2:
                                ((TopicFragment) getTargetFragment()).getBaseActivity().verifyStoragePermissions(getActivity(), new BaseActivity.ExternalPermissionCallback() {
                                    @Override
                                    public void granted() {
                                        File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
                                        ImageHandler.downloadImage(getActivity(), dir, uri, new ImageHandler.ImageDownloadCallback() {
                                            @Override
                                            public void onSuccess(Uri uri, File f) {
                                                getActivity().runOnUiThread(new Runnable() {
                                                    @Override
                                                    public void run() {
                                                        ((TopicFragment) getTargetFragment()).showSuccess(R.string.msg_img_download_success);
                                                    }
                                                });
                                            }

                                            @Override
                                            public void onFailure(Uri uri, Exception e) {
                                                getActivity().runOnUiThread(new Runnable() {
                                                    public void run() {
                                                        ((TopicFragment) getTargetFragment()).showError(R.string.msg_img_download_error);
                                                    }
                                                });
                                            }
                                        });
                                    }

                                    @Override
                                    public void denied() {
                                        ((TopicFragment) getTargetFragment()).showError(R.string.msg_permission_denied_error);
                                    }
                                });


                        }
                    }
                }).build();
    }

} public class LinkActionsDialog extends DialogFragment {

    public static final String ARG_IMAGE_URI = "link_uri";
    public static final String TAG = "linkmenu";

    public static LinkActionsDialog getInstance(Uri link_uri) {
        LinkActionsDialog f = new LinkActionsDialog();

        // Supply index input as an argument.
        Bundle args = new Bundle();
        args.putString(ARG_IMAGE_URI, link_uri.toString());
        f.setArguments(args);

        return f;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        return new MaterialDialog.Builder(getActivity())
                .title(R.string.link_dialog_title)
                .content(getArguments().getString(ARG_IMAGE_URI))
                .positiveText(R.string.link_dialog_goto)
                .negativeText(R.string.link_dialog_close)
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        Intent intent = new Intent(Intent.ACTION_VIEW);
                        intent.setData(Uri.parse(getArguments().getString(ARG_IMAGE_URI)));
                        startActivity(intent);
                    }
                })
                .build();
    }

} public class PostActionsDialog extends DialogFragment {

    public static final String ARG_POST_ID = "post_id";
    public static final String TAG = "postmenu";

    public static PostActionsDialog getInstance(int post_id) {
        PostActionsDialog f = new PostActionsDialog();

        // Supply index input as an argument.
        Bundle args = new Bundle();
        args.putInt(ARG_POST_ID, post_id);
        f.setArguments(args);

        return f;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final TopicFragment fragment = (TopicFragment) getTargetFragment();

        // get the menu items
        final String[] post_menu = getResources().getStringArray(R.array.post_dialog);

        final MaterialDialog dialog = new MaterialDialog.Builder(fragment.getBaseActivity())
                .items(post_menu)
                .title(R.string.post_dialog_title)
                .adapter(new PostActionAdapter(post_menu, getActivity(), fragment), null)
                .build();

        return dialog;
    }


    /**
     * Custom view adapter for the ListView items
     */
    public class PostActionAdapter extends RecyclerView.Adapter<PostActionsDialog.PostActionAdapter.ViewHolder> {
        private ArrayList<String> mDataset;
        TopicFragment mTarget;
        SettingsWrapper mSettings;

        @Override
        public PostActionsDialog.PostActionAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            FrameLayout v = (FrameLayout) LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.listitem_icon, parent, false);

            return new PostActionsDialog.PostActionAdapter.ViewHolder(v);
        }

        @Override
        public void onBindViewHolder(final PostActionsDialog.PostActionAdapter.ViewHolder holder, int position) {
            final String action = mDataset.get(position);

            holder.mText.setText(action);

            Post p = mTarget.getTopic().getPostById(getArguments().getInt(ARG_POST_ID));

            boolean isEnabled = true;
            switch (position) {
                case 0:
                    isEnabled = Utils.isLoggedIn() && mTarget.getTopic()
                            .getPostById(getArguments().getInt(ARG_POST_ID))
                            .getAuthor()
                            .getId() == mSettings.getUserId();
                    break;
                case 1:
                    isEnabled = Utils.isLoggedIn();
                    break;
                case 2:
                    isEnabled = Utils.isLoggedIn();
                    break;
                case 5:
                    isEnabled = Utils.isLoggedIn();
                    break;
                case 6:
                    isEnabled = Utils.isLoggedIn();
                    break;
                case 7:
                    isEnabled = Utils.isLoggedIn() && mTarget.getTopic().canHidePost() && !p.isHidden();
                    break;
                case 8:
                    isEnabled = Utils.isLoggedIn() && mTarget.getTopic().canHidePost() && !p.isTextHidden();
                    break;
                case 9:
                    isEnabled = Utils.isLoggedIn() && mTarget.getTopic().canHidePost() && (p.isHidden() || p.isTextHidden());
                    break;
            }

            //holder.mText.setEnabled(isEnabled);
            if(!isEnabled) {
                holder.itemView.setVisibility(View.GONE);
                holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
            }

            if(isEnabled) {
                holder.mText.setTextColor(Utils.getColorByAttr(getContext(), R.attr.md_content_color));
                holder.mRoot.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        switch (holder.getAdapterPosition()) {
                            case 0:
                                mTarget.editPost(getArguments().getInt(ARG_POST_ID));
                                break;
                            case 1:
                                mTarget.quotePost(getArguments().getInt(ARG_POST_ID));
                                break;
                            case 2:
                                mTarget.bookmarkPost(getArguments().getInt(ARG_POST_ID), null);
                                break;
                            case 3:
                                mTarget.savePost(getArguments().getInt(ARG_POST_ID));
                                break;
                            case 4:
                                mTarget.linkPost(getArguments().getInt(ARG_POST_ID));
                                break;
                            case 5:
                                mTarget.clipboardPostUrl(getArguments().getInt(ARG_POST_ID));
                                break;
                            case 6:
                                mTarget.pmToAuthor(getArguments().getInt(ARG_POST_ID));
                                break;
                            case 7:
                                mTarget.quickmodPostAction("hidereply", getArguments().getInt(ARG_POST_ID));
                                break;
                            case 8:
                                mTarget.quickmodPostAction("hidereplytext", getArguments().getInt(ARG_POST_ID));
                                break;
                            case 9:
                                mTarget.quickmodPostAction("unhidereply", getArguments().getInt(ARG_POST_ID));
                                break;
                        }
                        getDialog().dismiss();
                    }
                });
            } else
                holder.mText.setTextColor(Utils.getColorByAttr(getContext(), R.attr.md_content_color_disabled));
        }

        @Override
        public int getItemCount() {
            return mDataset.size();
        }

        class ViewHolder extends RecyclerView.ViewHolder {

            FrameLayout mRoot;
            TextView mText;

            ViewHolder(FrameLayout container) {
                super(container);
                mRoot = container;
                mText = (TextView) mRoot.findViewById(R.id.name);
            }
        }

        PostActionAdapter(String[] items, Context ctx, TopicFragment target) {
            mDataset = new ArrayList<>(Arrays.asList(items));
            mSettings = new SettingsWrapper(ctx);
            mTarget = target;
        }

    }

}
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.customtabs.CustomTabsIntent;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.Loader;
import android.support.v7.widget.Toolbar;
import android.text.Spanned;
import android.view.*;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.github.ksoichiro.android.observablescrollview.ObservableScrollViewCallbacks;
import com.github.ksoichiro.android.observablescrollview.ObservableWebView;
import com.github.ksoichiro.android.observablescrollview.ScrollState;
import com.mde.potdroid.EditorActivity;
import com.mde.potdroid.MediaActivity;
import com.mde.potdroid.R;
import com.mde.potdroid.helpers.*;
import com.mde.potdroid.helpers.ptr.SwipyRefreshLayoutDirection;
import com.mde.potdroid.models.Post;
import com.mde.potdroid.models.Topic;
import com.mde.potdroid.parsers.TopicParser;
import com.mde.potdroid.views.ChoosePageDialog;
import com.mde.potdroid.views.ImageActionsDialog;
import com.mde.potdroid.views.LinkActionsDialog;
import com.mde.potdroid.views.PostActionsDialog;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import org.apache.http.Header;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.text.SimpleDateFormat;
        refreshPaginateLayout();

    }

    public Topic getTopic() {
        return mTopic;
    }

    @Override
    public void onLoaderReset(Loader<Topic> loader) {
        hideLoadingAnimation();
    }

    public void goToNextPage() {

        if (mNextCache != null) {
            mJsInterface.registerScroll(0);

            // update the topic data
            mTopic = mNextCache;
            mNextCache = null;

            // Refresh the bookmarks after the topic loaded
            getBaseActivity().getLeftSidebarFragment().refreshBookmarks();

            displayContent();

            refreshTitleAndPagination();

            setSwipeEnabled(true);

            showFloatingActionButton();
        } else {

            // whether there is a next page was checked in onCreateOptionsMenu
            getArguments().putInt(ARG_PAGE, mTopic.getPage() + 1);
            getArguments().remove(ARG_POST_ID);
            mJsInterface.registerScroll(0);
            restartLoader(this);
        }

    }

    @Override
    public void nextButtonLongClick() {
        startPreloadingNextPage();
    }

    public void startPreloadingNextPage() {
        getArguments().putInt(ARG_PAGE, mTopic.getPage() + 1);
        getArguments().remove(ARG_POST_ID);
        restartLoader(this, true);
    }

    public void goToPage(int page) {
        if (page != mTopic.getPage()) {
            getArguments().putInt(ARG_PAGE, page);
            getArguments().remove(ARG_POST_ID);
            mJsInterface.registerScroll(0);
            restartLoader(this);
        }
    }

    public void goToPrevPage() {
        // whether there is a previous page was checked in onCreateOptionsMenu
        getArguments().putInt(ARG_PAGE, mTopic.getPage() - 1);
        getArguments().remove(ARG_POST_ID);
        mJsInterface.registerScroll(0);
        restartLoader(this);
    }

    public void goToFirstPage() {
        // whether there is a previous page was checked in onCreateOptionsMenu
        getArguments().putInt(ARG_PAGE, 1);
        getArguments().remove(ARG_POST_ID);
        mJsInterface.registerScroll(0);
        restartLoader(this);
    }

    @Override
    public boolean isLastPage() {
        return mTopic == null || mTopic.isLastPage();
    }

    @Override
    public boolean isFirstPage() {
        return mTopic == null || mTopic.getPage() == 1;
    }

    public void refreshPage() {
        restartLoader(this);
    }

    @Override
    public ViewGroup getSwipeView() {
        return null;
    }

    @Override
    public void goToLastPage() {
        // whether there is a previous page was checked in onCreateOptionsMenu
        getArguments().putInt(ARG_PAGE, mTopic.getNumberOfPages());
        getArguments().remove(ARG_POST_ID);
        restartLoader(this);
    }

    public void goToLastPost(int pid) {
        // whether there is a previous page was checked in onCreateOptionsMenu
        getArguments().putInt(ARG_POST_ID, pid);
        getArguments().remove(ARG_PAGE);
        restartLoader(this);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo
            menuInfo) {

        WebView.HitTestResult hitTestResult = mWebView.getHitTestResult();
        if (hitTestResult.getType() == WebView.HitTestResult.IMAGE_TYPE ||
                hitTestResult.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
            ImageActionsDialog imenu = ImageActionsDialog.getInstance(Uri.parse(hitTestResult.getExtra()));