def __init__(self, stdscr):
        self.stdscr = stdscr
        self.reddit_client = RedditClient()
        self.current_posts = []

        # get screen dimensions
        self.__max_y, self.__max_x = self.stdscr.getmaxyx()
class CursesClient(object):
    """
    Handles drawing the text based UI
    """
    __FLUSH = 0
    __MARGIN_Y = 2
    __MARGIN_X = 2

    def __init__(self, stdscr):
        self.stdscr = stdscr
        self.reddit_client = RedditClient()
        self.current_posts = []

        # get screen dimensions
        self.__max_y, self.__max_x = self.stdscr.getmaxyx()

    def __draw_scr_size(self):
        """
        Debug output to determine drawable screen size
        :return: void
        """
        str_scr_size = "{0}, {1}".format(self.__FLUSH, self.__max_x)
        self.stdscr.addstr(
            self.__FLUSH,
            self.__max_x - self.__MARGIN_X - len(str_scr_size),
            str_scr_size
        )

    def __draw_prompt(self):
        """
        Draw placeholder prompt
        :return: void
        """
        self.stdscr.addstr(
            self.__max_y - self.__MARGIN_Y,
            self.__FLUSH,
            ">"
        )

    def __draw_ch(self, input_char):
        """
        Debug output to draw last pressed key
        :param input_char: char of last input key
        :return: void
        """
        self.stdscr.addstr(
            self.__max_y - self.__MARGIN_Y,
            self.__FLUSH,
            ">{0}".format(str(input_char))
        )

    def __draw_page_num(self, page):
        """
        Draw placeholder current page number
        :param page: int page number
        :return: void
        """
        str_page_num = "page: {0}".format(page)
        self.stdscr.addstr(
            self.__max_y - self.__MARGIN_Y,
            self.__max_x - self.__MARGIN_X - len(str_page_num),
            str_page_num
        )

    def __draw_subreddit_name(self, subreddit, sort):
        """
        Draw placeholder subreddit name
        :param subreddit: string subreddit
        :param sort: string sort e.g. new, top, hot, etc
        :return:
        """
        str_scr_size = "r/{subreddit}/{sort}".format(
            subreddit=subreddit,
            sort=sort
        )
        self.stdscr.addstr(
            self.__FLUSH,
            self.__max_x - self.__MARGIN_X - len(str_scr_size),
            str_scr_size
        )

    def __subreddit_menu(self):
        """
        Switch to buffered input and prompt for subreddit name
        :return:  void
        """

        #flush input buffer
        flushinp()

        str_input_subreddit = "subreddit:"
        self.stdscr.addstr(
            self.__max_y - self.__MARGIN_Y,
            self.__FLUSH,
            str_input_subreddit
        )

        # disable cinput mode and enter buffered input mode and echo
        nocbreak()
        echo()
        input_buffer = self.stdscr.getstr()
        if input_buffer == "back":
            # enable cinput mode and disable echo
            cbreak()
            noecho()
        else:
            self.__posts_menu(input_buffer)

    def __posts_menu(self, subreddit):
        """
        Return to cinput mode and wait for key input
        :param subreddit: subreddit string
        :return: void
        """

        # enable cinput mode and disable echo
        cbreak()
        noecho()

        input_char = '_'
        direction = None
        anchor = None
        while input_char != ord('q'):

            # paging
            if input_char == KEY_RIGHT:
                direction = "after"
                anchor = self.current_posts[9]["data"]["name"]
            elif input_char == KEY_LEFT:
                direction = "before"
                anchor = self.current_posts[0]["data"]["name"]

            # post selection
            elif input_char >= 48 and input_char <= 57:
                self.__post_detail(self.current_posts[input_char - 48])

            # subreddit sorting
            elif input_char == ord('n'):
                sort = "new"
            elif input_char == ord('t'):
                sort = "top"
            elif input_char == ord('c'):
                sort = "controversial"
            elif input_char == ord('h'):
                sort = "hot"
            else:
                sort = "hot"

            self.current_posts = self.reddit_client.get_subreddit_posts(
                subreddit,
                sort,
                direction=direction,
                anchor=anchor
            )

            self.stdscr.clear()
            self.__draw_subreddit_name(subreddit, sort)
            self.__draw_ch(input_char)
            self.__draw_page_num(1)

            for post_num in range(len(self.current_posts)):
                post_title = filter_unicode(
                    self.current_posts[post_num]["data"]["title"]
                )
                self.stdscr.addstr(
                    post_num,
                    self.__FLUSH,
                    "{post_num} -> {title}".format(
                        post_num=post_num,
                        title=post_title
                    )
                )

            input_char = self.stdscr.getch()

    def __post_detail(self, post):
        """
        Placeholder display of post text, with placeholder text limit
        :param post: post self text string
        :return: void
        """

        input_char = ''
        while input_char != ord('q'):
            self.stdscr.clear()
            self.__draw_ch(input_char)

            # filter out unicode
            str_post = filter_unicode(post["data"]["selftext"])

            self.stdscr.addstr(
                self.__FLUSH,
                self.__FLUSH,
                str_post[:2000] or "No text found"
            )

            input_char = self.stdscr.getch()

    def top_menu(self):
        """
        Placeholder top level menu, only r for subreddits and q to quit
        :return: void
        """

        input_char = ''
        while input_char != ord('q'):
            self.stdscr.clear()
            self.__draw_scr_size()
            self.__draw_prompt()
            input_char = self.stdscr.getch()

            if input_char == ord('r'):
                self.__subreddit_menu()

    def run(self):
        """
        Main entry point
        :return: void
        """
        self.top_menu()
class TestRedditClient(object):

    @classmethod
    def setup_class(self):
        self.reddit_client = RedditClient()

    def test_access_token_not_none(self):
        assert_is_not_none(self.reddit_client.access_token)
        pprint(self.reddit_client.access_token)

    def test_get_subreddit_sidebar(self):
        json = self.reddit_client.get_subreddit_sidebar("civ")
        assert_is_not_none(json)
        assert_is_not_none(json["data"]["description"])
        assert_is_not_none(json["data"]["header_title"])
        assert_is_not_none(json["data"]["public_description"])
        pprint(json)

    def test_get_subreddit_hot(self):
        json = self.reddit_client.get_subreddit_posts("civ", "hot")
        assert_is_not_none(json)
        assert_is_not_none(json[0]["data"]["name"])
        assert_is_not_none(json[0]["data"]["title"])
        assert_is_not_none(json[0]["data"]["selftext"])
        pprint(json)

    def test_get_subreddit_top(self):
        json = self.reddit_client.get_subreddit_posts("civ", "top")
        assert_is_not_none(json)
        assert_is_not_none(json[0]["data"]["name"])
        assert_is_not_none(json[0]["data"]["title"])
        assert_is_not_none(json[0]["data"]["selftext"])
        pprint(json)

    def test_get_subreddit_new(self):
        json = self.reddit_client.get_subreddit_posts("civ", "new")
        assert_is_not_none(json)
        assert_is_not_none(json[0]["data"]["name"])
        assert_is_not_none(json[0]["data"]["title"])
        assert_is_not_none(json[0]["data"]["selftext"])
        pprint(json)

    def test_get_subreddit_controversial(self):
        json = self.reddit_client.get_subreddit_posts("civ", "controversial")
        assert_is_not_none(json)
        assert_is_not_none(json[0]["data"]["name"])
        assert_is_not_none(json[0]["data"]["title"])
        assert_is_not_none(json[0]["data"]["selftext"])
        pprint(json)

    def test_get_subreddit_page_after(self):
        anchor_json = self.reddit_client.get_subreddit_posts("civ", "new")
        anchor = anchor_json[0]["data"]["name"]
        json = self.reddit_client.get_subreddit_posts(
            "civ",
            "new",
            "after",
            anchor
        )
        assert_is_not_none(json)
        assert_is_not_none(json[0]["data"]["name"])
        assert_is_not_none(json[0]["data"]["title"])
        assert_is_not_none(json[0]["data"]["selftext"])
        pprint(json)

    def test_get_subreddit_page_before(self):
        anchor_after_json = self.reddit_client.get_subreddit_posts("civ", "new")
        anchor_after = anchor_after_json[0]["data"]["name"]
        anchor_before_json = self.reddit_client.get_subreddit_posts(
            "civ",
            "new",
            "after",
            anchor_after
        )
        anchor_before = anchor_before_json[0]["data"]["name"]
        json = self.reddit_client.get_subreddit_posts(
            "civ",
            "new",
            "before",
            anchor_before
        )
        assert_is_not_none(json)
        assert_is_not_none(json[0]["data"]["name"])
        assert_is_not_none(json[0]["data"]["title"])
        assert_is_not_none(json[0]["data"]["selftext"])
        pprint(json)
 def setup_class(self):
     self.reddit_client = RedditClient()