'Get the comment tree for a given Link `article`.
If supplied, `comment` is the ID36 of a comment in the comment tree for
`article`. This comment will be the (highlighted) focal point of the
returned view and `context` will be the number of parents shown.
`depth` is the maximum depth of subtrees in the thread.
`limit` is the maximum number of comments to return.
See also: [/api/morechildren](#GET_api_morechildren) and
[/api/comment](#POST_api_comment).'

@require_oauth2_scope('read')
@validate(article=VLink('article', docs={'article': 'ID36    of    a    link'}), comment=VCommentID('comment', docs={'comment': '(optional)    ID36    of    a    comment'}), context=VInt('context', min=0, max=8), sort=VOneOf('sort', CommentSortMenu._options), limit=VInt('limit', docs={'limit': '(optional)    an    integer'}), depth=VInt('depth', docs={'depth': '(optional)    an    integer'}), showedits=VBoolean('showedits', default=True), showmore=VBoolean('showmore', default=True), sr_detail=VBoolean('sr_detail', docs={'sr_detail': '(optional)    expand    subreddits'}))
@api_doc(api_section.listings, uri='/comments/{article}', uses_site=True, supports_rss=True)
def GET_comments(self, article, comment, context, sort, limit, depth, showedits=True, showmore=True, sr_detail=False):

    if (not sort):
        sort = c.user.pref_default_comment_sort
        if (sort == 'hot'):
            sort = 'confidence'
    if (comment and (comment.link_id != article._id)):
        return self.abort404()
    sr = Subreddit._byID(article.sr_id, True)
    if (sr.name == g.takedown_sr):
        request.environ['REDDIT_TAKEDOWN'] = article._fullname
        return self.abort404()
    if ((not c.default_sr) and (c.site._id != sr._id)):
        return self.abort404()
    if (not can_view_link_comments(article)):
        abort(403, 'forbidden')
    if (article.is_nsfw and (not c.over18) and (c.render_style == 'html') and (not request.parsed_agent.bot)):
        return self.intermediate_redirect('/over18', sr_path=False)
    canonical_link = article.make_canonical_link(sr)
    c.can_embed = (bool(comment) and article.is_embeddable)
    is_embed = embeds.prepare_embed_request()
    if (is_embed and comment):
        embeds.set_up_comment_embed(sr, comment, showedits=showedits)
    page = hooks.get_hook('comments_page.override').call_until_return(controller=self, article=article, limit=limit)
    if page:
        return page
    previous_visits = None
    if comment:
        c.focal_comment = comment._id36
    elif (c.user_is_loggedin and (c.user.gold or sr.is_moderator(c.user)) and c.user.pref_highlight_new_comments):
        timer = g.stats.get_timer('gold.comment_visits')
        timer.start()
        previous_visits = CommentVisitsByUser.get_and_update(c.user, article, c.start_time)
        timer.stop()
    infotext = None
    infotext_class = None
    infotext_show_icon = False
    if request.GET.get('already_submitted'):
        submit_url = (request.GET.get('submit_url') or article.url)
        submit_title = (request.GET.get('submit_title') or '')
        resubmit_url = Link.resubmit_link(submit_url, submit_title)
        if (c.user_is_loggedin and c.site.can_submit(c.user)):
            resubmit_url = add_sr(resubmit_url)
        infotext = (strings.already_submitted % resubmit_url)
    elif article.archived_slow:
        infotext = strings.archived_post_message
        infotext_class = 'archived-infobar'
        infotext_show_icon = True
    elif article.locked:
        infotext = strings.locked_post_message
        infotext_class = 'locked-infobar'
        infotext_show_icon = True
    if (not c.user.pref_num_comments):
        num = g.num_comments
    elif (c.user_is_loggedin and (c.user.gold or sr.is_moderator(c.user))):
        num = min(c.user.pref_num_comments, g.max_comments_gold)
    else:
        num = min(c.user.pref_num_comments, g.max_comments)
    kw = {}
    if ((depth is not None) and (0 < depth < MAX_RECURSION)):
        kw['max_depth'] = depth
    elif (c.render_style == 'compact'):
        kw['max_depth'] = 5
    kw['edits_visible'] = showedits
    kw['load_more'] = kw['continue_this_thread'] = showmore
    kw['show_deleted'] = embeds.is_embed()
    displayPane = PaneStack()
    if (limit and (limit > 0)):
        num = limit
    if (c.user_is_loggedin and (c.user.gold or sr.is_moderator(c.user))):
        if (num > g.max_comments_gold):
            displayPane.append(InfoBar(message=(strings.over_comment_limit_gold % max(0, g.max_comments_gold))))
            num = g.max_comments_gold
    elif (num > g.max_comments):
        if limit:
            displayPane.append(InfoBar(message=(strings.over_comment_limit % dict(max=max(0, g.max_comments), goldmax=max(0, g.max_comments_gold)))))
        num = g.max_comments
    page_classes = ['comments-page']
    if comment:
        displayPane.append(PermalinkMessage(article.make_permalink_slow()))
        page_classes.append('comment-permalink-page')
    displayPane.append(LinkCommentSep())
    if ((not is_api()) and c.user_is_loggedin and article.can_comment_slow(c.user)):
        display = (not comment)
        if article.promoted:
            (geotargeted, city_target) = promote.is_geotargeted_promo(article)
            if geotargeted:
                displayPane.append(GeotargetNotice(city_target=city_target))
        data_attrs = {'type': 'link', 'event-action': 'comment'}
        displayPane.append(UserText(item=article, creating=True, post_form='comment', display=display, cloneable=True, data_attrs=data_attrs))
    if previous_visits:
        displayPane.append(CommentVisitsBox(previous_visits))
    if c.site.allows_referrers:
        c.referrer_policy = 'always'
    suggested_sort_active = False
    if (not c.user.pref_ignore_suggested_sort):
        suggested_sort = article.sort_if_suggested()
    else:
        suggested_sort = None
    if ((suggested_sort == 'qa') and c.user_is_loggedin and (c.user._id in article.responder_ids)):
        suggested_sort = None
    if article.contest_mode:
        if (c.user_is_loggedin and sr.is_moderator(c.user)):
            if ('sort' not in request.params):
                sort = 'top'
        else:
            sort = 'random'
    elif (suggested_sort and ('sort' not in request.params)):
        sort = suggested_sort
        suggested_sort_active = True
    displayPane.append(CommentPane(article, CommentSortMenu.operator(sort), comment, context, num, **kw))
    subtitle_buttons = []
    disable_comments = (article.promoted and article.disable_comments)
    if (c.focal_comment or (context is not None) or disable_comments):
        subtitle = None
    elif (article.num_comments == 0):
        subtitle = _('no    comments    (yet)')
    elif (article.num_comments <= num):
        subtitle = (_('all    %d    comments') % article.num_comments)
    else:
        subtitle = (_('top    %d    comments') % num)
        if (g.max_comments > num):
            self._add_show_comments_link(subtitle_buttons, article, num, g.max_comments, gold=False)
        if (c.user_is_loggedin and (c.user.gold or sr.is_moderator(c.user)) and (article.num_comments > g.max_comments)):
            self._add_show_comments_link(subtitle_buttons, article, num, g.max_comments_gold, gold=True)
    sort_menu = CommentSortMenu(default=sort, css_class=('suggested' if suggested_sort_active else ''), suggested_sort=suggested_sort)
    link_settings = LinkCommentsSettings(article, sort=sort, suggested_sort=suggested_sort)
    click_url = None
    campaign_fullname = None
    if (article.promoted and (not article.is_self)):
        campaign_fullname = request.GET.get('campaign', None)
        click_url = request.GET.get('click_url', None)
        click_hash = request.GET.get('click_hash', '')
        if (click_url and (not promote.is_valid_click_url(link=article, click_url=click_url, click_hash=click_hash))):
            click_url = None
    if comment:
        event_target = {'target_type': 'comment', 'target_fullname': comment._fullname, 'target_id': comment._id}
    elif article.is_self:
        event_target = {'target_type': 'self', 'target_fullname': article._fullname, 'target_id': article._id, 'target_sort': sort}
    else:
        event_target = {'target_type': 'link', 'target_fullname': article._fullname, 'target_id': article._id, 'target_url': article.url, 'target_url_domain': article.link_domain(), 'target_sort': sort}
    extra_js_config = {'event_target': event_target}
    res = LinkInfoPage(link=article, comment=comment, disable_comments=disable_comments, content=displayPane, page_classes=page_classes, subtitle=subtitle, subtitle_buttons=subtitle_buttons, nav_menus=[sort_menu, link_settings], infotext=infotext, infotext_class=infotext_class, infotext_show_icon=infotext_show_icon, sr_detail=sr_detail, campaign_fullname=campaign_fullname, click_url=click_url, canonical_link=canonical_link, extra_js_config=extra_js_config)
    return res.render()
