# coding: utf-8

import logging
import requests
import mimetypes
from io import BytesIO
from urllib.parse import urlparse
from datetime import datetime, timedelta
from collections import OrderedDict
from flask_babelex import gettext as _
from flask import (
    render_template,
    abort,
    current_app,
    request,
    session,
    redirect,
    jsonify,
    url_for,
    Response,
    send_from_directory,
    g,
    make_response,
)
from werkzeug.contrib.atom import AtomFeed
from urllib.parse import urljoin
from legendarium.formatter import descriptive_short_format

from . import main
from webapp import babel
from webapp import cache
from webapp import controllers
from webapp.choices import STUDY_AREAS
from webapp.utils import utils
from webapp.utils.caching import cache_key_with_lang, cache_key_with_lang_with_qs
from webapp import forms

from webapp.config.lang_names import display_original_lang_name

from opac_schema.v1.models import Journal, Issue, Article, Collection

from lxml import etree
from packtools import HTMLGenerator

logger = logging.getLogger(__name__)

JOURNAL_UNPUBLISH = _("O periódico está indisponível por motivo de: ")
ISSUE_UNPUBLISH = _("O número está indisponível por motivo de: ")
ARTICLE_UNPUBLISH = _("O artigo está indisponível por motivo de: ")

IAHX_LANGS = dict(
    p='pt',
    e='es',
    i='en',
)


def url_external(endpoint, **kwargs):
    url = url_for(endpoint, **kwargs)
    return urljoin(request.url_root, url)


class RetryableError(Exception):
    """Erro recuperável sem que seja necessário modificar o estado dos dados
    na parte cliente, e.g., timeouts, erros advindos de particionamento de rede
    etc.
    """


class NonRetryableError(Exception):
    """Erro do qual não pode ser recuperado sem modificar o estado dos dados
    na parte cliente, e.g., recurso solicitado não exite, URI inválida etc.
    """


def fetch_data(url: str, timeout: float = 2) -> bytes:
    try:
        response = requests.get(url, timeout=timeout)
    except (requests.ConnectionError, requests.Timeout) as exc:
        raise RetryableError(exc) from exc
    except (requests.InvalidSchema, requests.MissingSchema, requests.InvalidURL) as exc:
        raise NonRetryableError(exc) from exc
    else:
        try:
            response.raise_for_status()
        except requests.HTTPError as exc:
            if 400 <= exc.response.status_code < 500:
                raise NonRetryableError(exc) from exc
            elif 500 <= exc.response.status_code < 600:
                raise RetryableError(exc) from exc
            else:
                raise

    return response.content


@main.before_app_request
def add_collection_to_g():

    if not hasattr(g, 'collection'):
        try:
            collection = controllers.get_current_collection()
            setattr(g, 'collection', collection)
        except Exception:
            # discutir o que fazer aqui
            setattr(g, 'collection', {})


@main.after_request
def add_header(response):
    response.headers['x-content-type-options'] = 'nosniff'
    return response

@main.after_request
def add_language_code(response):
    language = session.get('lang', get_locale())
    response.set_cookie('language', language)
    return response


@main.before_app_request
def add_forms_to_g():
    setattr(g, 'email_share', forms.EmailShareForm())
    setattr(g, 'email_contact', forms.ContactForm())
    setattr(g, 'error', forms.ErrorForm())


@main.before_app_request
def add_scielo_org_config_to_g():
    language = session.get('lang', get_locale())
    scielo_org_links = {
        key: url[language]
        for key, url in current_app.config.get('SCIELO_ORG_URIS', {}).items()
    }
    setattr(g, 'scielo_org', scielo_org_links)


@babel.localeselector
def get_locale():
    langs = current_app.config.get('LANGUAGES')
    lang_from_headers = request.accept_languages.best_match(list(langs.keys()))

    if 'lang' not in list(session.keys()):
        session['lang'] = lang_from_headers

    if not lang_from_headers and not session['lang']:
        # Caso não seja possível detectar o idioma e não tenhamos a chave lang
        # no seção, fixamos o idioma padrão.
        session['lang'] = current_app.config.get('BABEL_DEFAULT_LOCALE')

    return session['lang']


@main.route('/set_locale/<string:lang_code>/')
def set_locale(lang_code):
    langs = current_app.config.get('LANGUAGES')

    if lang_code not in list(langs.keys()):
        abort(400, _('Código de idioma inválido'))

    referrer = request.referrer
    hash = request.args.get('hash')
    if hash:
        referrer += "#" + hash

    # salvar o lang code na sessão
    session['lang'] = lang_code
    return redirect(referrer)


def get_lang_from_session():
    """
    Tenta retornar o idioma da seção, caso não consiga retorna
    BABEL_DEFAULT_LOCALE.
    """
    try:
        return session['lang']
    except KeyError:
        return current_app.config.get('BABEL_DEFAULT_LOCALE')


@main.route('/')
@cache.cached(key_prefix=cache_key_with_lang)
def index():
    language = session.get('lang', get_locale())
    news = controllers.get_latest_news_by_lang(language)

    tweets = controllers.get_collection_tweets()
    press_releases = controllers.get_press_releases({'language': language})

    urls = {
        'downloads': '{0}/w/accesses?collection={1}'.format(
            current_app.config['METRICS_URL'],
            current_app.config['OPAC_COLLECTION']),
        'references': '{0}/w/publication/size?collection={1}'.format(
            current_app.config['METRICS_URL'],
            current_app.config['OPAC_COLLECTION']),
        'other': '{0}/?collection={1}'.format(
            current_app.config['METRICS_URL'],
            current_app.config['OPAC_COLLECTION'])
    }

    if (
        g.collection is not None
        and isinstance(g.collection, Collection)
        and g.collection.metrics is not None
        and current_app.config['USE_HOME_METRICS']
    ):
        g.collection.metrics.total_journal = Journal.objects.filter(
            is_public=True, current_status="current"
        ).count()
        g.collection.metrics.total_article = Article.objects.filter(
            is_public=True
        ).count()

    context = {
        'news': news,
        'urls': urls,
        'tweets': tweets,
        'press_releases': press_releases,
    }

    return render_template("collection/index.html", **context)


# ##################################Collection###################################


@main.route('/journals/alpha')
@cache.cached(key_prefix=cache_key_with_lang)
def collection_list():
    allowed_filters = ["current", "no-current", ""]
    query_filter = request.args.get("status", "")

    if not query_filter in allowed_filters:
        query_filter = ""

    journals_list = [
        controllers.get_journal_json_data(journal)
        for journal in controllers.get_journals(query_filter=query_filter)
    ]

    return render_template("collection/list_journal.html",
                           **{'journals_list': journals_list, 'query_filter': query_filter})


@main.route("/journals/thematic")
@cache.cached(key_prefix=cache_key_with_lang)
def collection_list_thematic():
    allowed_query_filters = ["current", "no-current", ""]
    allowed_thematic_filters = ["areas", "wos", "publisher"]
    thematic_table = {
        "areas": "study_areas",
        "wos": "subject_categories",
        "publisher": "publisher_name",
    }
    query_filter = request.args.get("status", "")
    title_query = request.args.get("query", "")
    thematic_filter = request.args.get("filter", "areas")

    if not query_filter in allowed_query_filters:
        query_filter = ""

    if not thematic_filter in allowed_thematic_filters:
        thematic_filter = "areas"

    lang = get_lang_from_session()[:2].lower()
    objects = controllers.get_journals_grouped_by(
        thematic_table[thematic_filter],
        title_query,
        query_filter=query_filter,
        lang=lang,
    )

    return render_template(
        "collection/list_thematic.html",
        **{"objects": objects, "query_filter": query_filter, "filter": thematic_filter}
    )


@main.route('/journals/feed/')
@cache.cached(key_prefix=cache_key_with_lang)
def collection_list_feed():
    language = session.get('lang', get_locale())
    collection = controllers.get_current_collection()

    title = 'SciELO - %s - %s' % (collection.name, _('Últimos periódicos inseridos na coleção'))
    subtitle = _('10 últimos periódicos inseridos na coleção %s' % collection.name)

    feed = AtomFeed(title,
                    subtitle=subtitle,
                    feed_url=request.url, url=request.url_root)

    journals = controllers.get_journals_paginated(
        title_query='', page=1, order_by='-created', per_page=10)

    if not journals.items:
        feed.add('Nenhum periódico encontrado',
                 url=request.url,
                 updated=datetime.now())

    for journal in journals.items:
        issues = controllers.get_issues_by_jid(journal.jid, is_public=True)
        last_issue = issues[0] if issues else None

        articles = []
        if last_issue:
            articles = controllers.get_articles_by_iid(last_issue.iid,
                                                       is_public=True)

        result_dict = OrderedDict()
        for article in articles:
            section = article.get_section_by_lang(language[:2])
            result_dict.setdefault(section, [])
            result_dict[section].append(article)

        context = {
            'journal': journal,
            'articles': result_dict,
            'language': language,
            'last_issue': last_issue
        }

        feed.add(journal.title,
                 render_template("collection/list_feed_content.html", **context),
                 content_type='html',
                 author=journal.publisher_name,
                 url=url_external('main.journal_detail', url_seg=journal.url_segment),
                 updated=journal.updated,
                 published=journal.created)

    return feed.get_response()


@main.route("/about/", methods=['GET'])
@main.route('/about/<string:slug_name>', methods=['GET'])
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def about_collection(slug_name=None):
    language = session.get('lang', get_locale())

    context = {}
    page = None
    if slug_name:
        # caso seja uma página
        page = controllers.get_page_by_slug_name(slug_name, language)
        if not page:
            abort(404, _('Página não encontrada'))
        context['page'] = page
    else:
        # caso não seja uma página é uma lista
        pages = controllers.get_pages_by_lang(language)
        context['pages'] = pages

    return render_template("collection/about.html", **context)


# ###################################Journal#####################################


@main.route('/scielo.php/')
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def router_legacy():

    script_php = request.args.get('script', None)
    pid = request.args.get('pid', None)
    tlng = request.args.get('tlng', None)
    allowed_scripts = [
        'sci_serial', 'sci_issuetoc', 'sci_arttext', 'sci_abstract', 'sci_issues', 'sci_pdf'
    ]
    if (script_php is not None) and (script_php in allowed_scripts) and not pid:
        # se tem pelo menos um param: pid ou script_php
        abort(400, _(u'Requsição inválida ao tentar acessar o artigo com pid: %s' % pid))
    elif script_php and pid:

        if script_php == 'sci_serial':
            # pid = issn
            journal = controllers.get_journal_by_issn(pid)

            if not journal:
                abort(404, _('Periódico não encontrado'))

            if not journal.is_public:
                abort(404, JOURNAL_UNPUBLISH + _(journal.unpublish_reason))

            return redirect(url_for('main.journal_detail',
                            url_seg=journal.url_segment), code=301)

        elif script_php == 'sci_issuetoc':

            issue = controllers.get_issue_by_pid(pid)

            if not issue:
                abort(404, _('Número não encontrado'))

            if not issue.is_public:
                abort(404, ISSUE_UNPUBLISH + _(issue.unpublish_reason))

            if not issue.journal.is_public:
                abort(404, JOURNAL_UNPUBLISH + _(issue.journal.unpublish_reason))

            if issue.url_segment and "ahead" in issue.url_segment:
                return redirect(
                    url_for('main.aop_toc', url_seg=url_seg), code=301)

            return redirect(
                url_for(
                    "main.issue_toc",
                    url_seg=issue.journal.url_segment,
                    url_seg_issue=issue.url_segment),
                301
            )

        elif script_php == 'sci_arttext' or script_php == 'sci_abstract':
            article = controllers.get_article_by_pid_v2(pid)
            if not article:
                abort(404, _('Artigo não encontrado'))

            # 'abstract' or None (not False, porque False converterá a string 'False')
            part = (script_php == 'sci_abstract' and 'abstract') or None

            if tlng not in article.languages:
                tlng = article.original_language

            return redirect(url_for('main.article_detail_v3',
                                    url_seg=article.journal.url_segment,
                                    article_pid_v3=article.aid,
                                    part=part,
                                    lang=tlng),
                            code=301)

        elif script_php == 'sci_issues':

            journal = controllers.get_journal_by_issn(pid)

            if not journal:
                abort(404, _('Periódico não encontrado'))

            if not journal.is_public:
                abort(404, JOURNAL_UNPUBLISH + _(journal.unpublish_reason))

            return redirect(url_for('main.issue_grid',
                                    url_seg=journal.url_segment), 301)

        elif script_php == 'sci_pdf':
            # accesso ao pdf do artigo:
            article = controllers.get_article_by_pid_v2(pid)
            if not article:
                abort(404, _('Artigo não encontrado'))

            return redirect(
                url_for(
                    'main.article_detail_v3',
                    url_seg=article.journal.url_segment,
                    article_pid_v3=article.aid,
                    format='pdf',
                ),
                code=301
            )

        else:
            abort(400, _(u'Requsição inválida ao tentar acessar o artigo com pid: %s' % pid))

    else:
        return redirect('/')


@main.route('/<string:journal_seg>')
@main.route('/journal/<string:journal_seg>')
def journal_detail_legacy_url(journal_seg):
    return redirect(url_for('main.journal_detail',
                            url_seg=journal_seg), code=301)


@main.route('/j/<string:url_seg>/')
@cache.cached(key_prefix=cache_key_with_lang)
def journal_detail(url_seg):
    journal = controllers.get_journal_by_url_seg(url_seg)

    if not journal:
        abort(404, _('Periódico não encontrado'))

    if not journal.is_public:
        abort(404, JOURNAL_UNPUBLISH + _(journal.unpublish_reason))

    utils.fix_journal_last_issue(journal)

    # todo: ajustar para que seja só noticias relacionadas ao periódico
    language = session.get('lang', get_locale())
    news = controllers.get_latest_news_by_lang(language)

    # Press releases
    press_releases = controllers.get_press_releases({
        'journal': journal,
        'language': language})

    # Lista de seções
    # Mantendo sempre o idioma inglês para as seções na página incial do periódico
    if journal.last_issue and journal.current_status == "current":
        sections = [section for section in journal.last_issue.sections if section.language == 'en']
        recent_articles = controllers.get_recent_articles_of_issue(journal.last_issue.iid, is_public=True)
    else:
        sections = []
        recent_articles = []

    latest_issue = journal.last_issue

    if latest_issue:
        latest_issue_legend = descriptive_short_format(
            title=journal.title, short_title=journal.short_title,
            pubdate=str(latest_issue.year), volume=latest_issue.volume, number=latest_issue.number,
            suppl=latest_issue.suppl_text, language=language[:2].lower())
    else:
        latest_issue_legend = ''

    journal_metrics = controllers.get_journal_metrics(journal)

    context = {
        'journal': journal,
        'press_releases': press_releases,
        'recent_articles': recent_articles,
        'journal_study_areas': [
            STUDY_AREAS.get(study_area.upper()) for study_area in journal.study_areas
        ],
        # o primiero item da lista é o último número.
        # condicional para verificar se issues contém itens
        'last_issue': latest_issue,
        'latest_issue_legend': latest_issue_legend,
        'sections': sections if sections else None,
        'news': news,
        'journal_metrics': journal_metrics
    }

    return render_template("journal/detail.html", **context)


@main.route('/journal/<string:url_seg>/feed/')
@cache.cached(key_prefix=cache_key_with_lang)
def journal_feed(url_seg):
    journal = controllers.get_journal_by_url_seg(url_seg)

    if not journal:
        abort(404, _('Periódico não encontrado'))

    if not journal.is_public:
        abort(404, JOURNAL_UNPUBLISH + _(journal.unpublish_reason))

    issues = controllers.get_issues_by_jid(journal.jid, is_public=True)
    last_issue = issues[0] if issues else None
    articles = controllers.get_articles_by_iid(last_issue.iid, is_public=True)

    feed = AtomFeed(journal.title,
                    feed_url=request.url,
                    url=request.url_root,
                    subtitle=utils.get_label_issue(last_issue))

    feed_language = session.get('lang', get_locale())
    feed_language = feed_language[:2].lower()

    for article in articles:

        # ######### TODO: Revisar #########
        article_lang = feed_language
        if feed_language not in article.languages:
            article_lang = article.original_language

        feed.add(article.title or _('Artigo sem título'),
                 render_template("issue/feed_content.html", article=article),
                 content_type='html',
                 id=article.doi or article.pid,
                 author=article.authors,
                 url=url_external('main.article_detail_v3',
                                  url_seg=journal.url_segment,
                                  article_pid_v3=article.aid,
                                  lang=article_lang),
                 updated=journal.updated,
                 published=journal.created)

    return feed.get_response()


@main.route("/journal/<string:url_seg>/about/", methods=['GET'])
@cache.cached(key_prefix=cache_key_with_lang)
def about_journal(url_seg):
    language = session.get('lang', get_locale())

    journal = controllers.get_journal_by_url_seg(url_seg)

    if not journal:
        abort(404, _('Periódico não encontrado'))

    if not journal.is_public:
        abort(404, JOURNAL_UNPUBLISH + _(journal.unpublish_reason))

    latest_issue = utils.fix_journal_last_issue(journal)

    if latest_issue:
        latest_issue_legend = descriptive_short_format(
            title=journal.title, short_title=journal.short_title,
            pubdate=str(latest_issue.year), volume=latest_issue.volume, number=latest_issue.number,
            suppl=latest_issue.suppl_text, language=language[:2].lower())
    else:
        latest_issue_legend = None

    page = controllers.get_page_by_journal_acron_lang(journal.acronym, language)

    context = {
        'journal': journal,
        'latest_issue_legend': latest_issue_legend,
        'last_issue': latest_issue,
        'journal_study_areas': [
            STUDY_AREAS.get(study_area.upper()) for study_area in journal.study_areas
        ],
    }

    if page:
        context['content'] = page.content
        if page.updated_at:
            context['page_updated_at'] = page.updated_at

    return render_template("journal/about.html", **context)


@main.route("/journals/search/alpha/ajax/", methods=['GET', ])
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def journals_search_alpha_ajax():

    if not request.is_xhr:
        abort(400, _('Requisição inválida. Deve ser por ajax'))

    query = request.args.get('query', '', type=str)
    query_filter = request.args.get('query_filter', '', type=str)
    page = request.args.get('page', 1, type=int)
    lang = get_lang_from_session()[:2].lower()

    response_data = controllers.get_alpha_list_from_paginated_journals(
                        title_query=query,
                        query_filter=query_filter,
                        page=page,
                        lang=lang)

    return jsonify(response_data)


@main.route("/journals/search/group/by/filter/ajax/", methods=['GET'])
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def journals_search_by_theme_ajax():

    if not request.is_xhr:
        abort(400, _('Requisição inválida. Deve ser por ajax'))

    query = request.args.get('query', '', type=str)
    query_filter = request.args.get('query_filter', '', type=str)
    filter = request.args.get('filter', 'areas', type=str)
    lang = get_lang_from_session()[:2].lower()

    if filter == 'areas':
        objects = controllers.get_journals_grouped_by('study_areas', query, query_filter=query_filter, lang=lang)
    elif filter == 'wos':
        objects = controllers.get_journals_grouped_by('subject_categories', query, query_filter=query_filter, lang=lang)
    elif filter == 'publisher':
        objects = controllers.get_journals_grouped_by('publisher_name', query, query_filter=query_filter, lang=lang)
    else:
        return jsonify({
            'error': 401,
            'message': _('Parámetro "filter" é inválido, deve ser "areas", "wos" ou "publisher".')
        })
    return jsonify(objects)


@main.route("/journals/download/<string:list_type>/<string:extension>/", methods=['GET', ])
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def download_journal_list(list_type, extension):
    if extension.lower() not in ['csv', 'xls']:
        abort(401, _('Parámetro "extension" é inválido, deve ser "csv" ou "xls".'))
    elif list_type.lower() not in ['alpha', 'areas', 'wos', 'publisher']:
        abort(401, _('Parámetro "list_type" é inválido, deve ser: "alpha", "areas", "wos" ou "publisher".'))
    else:
        if extension.lower() == 'xls':
            mimetype = 'application/vnd.ms-excel'
        else:
            mimetype = 'text/csv'
        query = request.args.get('query', '', type=str)
        data = controllers.get_journal_generator_for_csv(list_type=list_type,
                                                         title_query=query,
                                                         extension=extension.lower())
        timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
        filename = 'journals_%s_%s.%s' % (list_type, timestamp, extension)
        response = Response(data, mimetype=mimetype)
        response.headers['Content-Disposition'] = 'attachment; filename=%s' % filename
        return response


@main.route("/<string:url_seg>/contact", methods=['POST'])
def contact(url_seg):

    if not request.is_xhr:
        abort(403, _('Requisição inválida, deve ser ajax.'))

    if utils.is_recaptcha_valid(request):

        form = forms.ContactForm(request.form)

        journal = controllers.get_journal_by_url_seg(url_seg)

        if not journal.enable_contact:
            abort(403, _('Periódico não permite envio de email.'))

        recipients = journal.editor_email

        if form.validate():
            sent, message = controllers.send_email_contact(recipients,
                                                           form.data['name'],
                                                           form.data['your_email'],
                                                           form.data['message'])

            return jsonify({'sent': sent, 'message': str(message),
                            'fields': [key for key in form.data.keys()]})

        else:
            return jsonify({'sent': False, 'message': form.errors,
                            'fields': [key for key in form.data.keys()]})

    else:
        abort(400, _('Requisição inválida, captcha inválido.'))


@main.route("/form_contact/<string:url_seg>/", methods=['GET'])
def form_contact(url_seg):
    journal = controllers.get_journal_by_url_seg(url_seg)
    if not journal:
        abort(404, _('Periódico não encontrado'))

    context = {
        'journal': journal
    }
    return render_template("journal/includes/contact_form.html", **context)


# ###################################Issue#######################################


@main.route('/grid/<string:url_seg>/')
def issue_grid_legacy(url_seg):
    return redirect(url_for('main.issue_grid', url_seg=url_seg), 301)


@main.route('/j/<string:url_seg>/grid')
@cache.cached(key_prefix=cache_key_with_lang)
def issue_grid(url_seg):
    journal = controllers.get_journal_by_url_seg(url_seg)

    if not journal:
        abort(404, _('Periódico não encontrado'))

    if not journal.is_public:
        abort(404, JOURNAL_UNPUBLISH + _(journal.unpublish_reason))

    # idioma da sessão
    language = session.get('lang', get_locale())

    # A ordenação padrão da função ``get_issues_by_jid``: "-year", "-volume", "-order"
    issues_data = controllers.get_issues_for_grid_by_jid(journal.id, is_public=True)
    latest_issue = issues_data['last_issue']
    if latest_issue:
        latest_issue_legend = descriptive_short_format(
            title=journal.title, short_title=journal.short_title,
            pubdate=str(latest_issue.year), volume=latest_issue.volume, number=latest_issue.number,
            suppl=latest_issue.suppl_text, language=language[:2].lower())
    else:
        latest_issue_legend = None

    context = {
        'journal': journal,
        'last_issue': issues_data['last_issue'],
        'latest_issue_legend': latest_issue_legend,
        'volume_issue': issues_data['volume_issue'],
        'ahead': issues_data['ahead'],
        'result_dict': issues_data['ordered_for_grid'],
        'journal_study_areas': [
            STUDY_AREAS.get(study_area.upper()) for study_area in journal.study_areas
        ],
    }

    return render_template("issue/grid.html", **context)


@main.route('/toc/<string:url_seg>/<string:url_seg_issue>/')
def issue_toc_legacy(url_seg, url_seg_issue):
    if url_seg_issue and "ahead" in url_seg_issue:
        return redirect(url_for('main.aop_toc', url_seg=url_seg), code=301)

    return redirect(
        url_for('main.issue_toc',
                url_seg=url_seg,
                url_seg_issue=url_seg_issue),
        code=301)


@main.route('/j/<string:url_seg>/i/<string:url_seg_issue>/')
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def issue_toc(url_seg, url_seg_issue):
    section_filter = None
    goto = request.args.get("goto", None, type=str)
    if goto not in ("previous", "next"):
        goto = None

    if goto in (None, "next") and "ahead" in url_seg_issue:
        # redireciona para `aop_toc`
        return redirect(url_for('main.aop_toc', url_seg=url_seg), code=301)

    # idioma da sessão
    language = session.get('lang', get_locale())

    if current_app.config["FILTER_SECTION_ENABLE"]:
        # seção dos documentos, se selecionada
        section_filter = request.args.get('section', '', type=str).upper()

    # obtém o issue
    issue = controllers.get_issue_by_url_seg(url_seg, url_seg_issue)
    if not issue:
        abort(404, _('Número não encontrado'))
    if not issue.is_public:
        abort(404, ISSUE_UNPUBLISH + _(issue.unpublish_reason))

    # obtém o journal
    journal = issue.journal
    if not journal.is_public:
        abort(404, JOURNAL_UNPUBLISH + _(journal.unpublish_reason))

    # completa url_segment do last_issue
    utils.fix_journal_last_issue(journal)

    # goto_next_or_previous_issue (redireciona)
    goto_url = goto_next_or_previous_issue(
        issue, request.args.get('goto', None, type=str))
    if goto_url:
        return redirect(goto_url, code=301)

    # obtém os documentos
    articles = controllers.get_articles_by_iid(issue.iid, is_public=True)
    if articles:
        # obtém TODAS as seções dos documentos deste sumário
        sections = sorted({a.section.upper() for a in articles if a.section})
    else:
        # obtém as seções dos documentos deste sumário
        sections = []

    if current_app.config["FILTER_SECTION_ENABLE"] and section_filter != '':
        # obtém somente os documentos da seção selecionada
        articles = [a for a in articles if a.section.upper() == section_filter]

    # obtém PDF e TEXT de cada documento
    has_math_content = False
    for article in articles:
        article_text_languages = [doc['lang'] for doc in article.htmls]
        article_pdf_languages = [(doc['lang'], doc['url']) for doc in article.pdfs]
        setattr(article, "article_text_languages", article_text_languages)
        setattr(article, "article_pdf_languages", article_pdf_languages)
        if 'mml:' in article.title:
            has_math_content = True

    # obtém a legenda bibliográfica
    issue_bibliographic_strip = descriptive_short_format(
        title=journal.title, short_title=journal.short_title,
        pubdate=str(issue.year), volume=issue.volume, number=issue.number,
        suppl=issue.suppl_text, language=language[:2].lower())

    context = {
        'this_page_url': url_for(
                            'main.issue_toc',
                            url_seg=url_seg,
                            url_seg_issue=url_seg_issue),
        'has_math_content': has_math_content,
        'journal': journal,
        'issue': issue,
        'issue_bibliographic_strip': issue_bibliographic_strip,
        'articles': articles,
        'sections': sections,
        'section_filter': section_filter,
        'journal_study_areas': [
            STUDY_AREAS.get(study_area.upper()) for study_area in journal.study_areas
        ],
        'last_issue': journal.last_issue
    }
    return render_template("issue/toc.html", **context)


def goto_next_or_previous_issue(current_issue, goto_param):
    if goto_param not in ["next", "previous"]:
        return None

    all_issues = list(
        controllers.get_issues_by_jid(current_issue.journal.id, is_public=True))
    if goto_param == "next":
        selected_issue = utils.get_next_issue(all_issues, current_issue)
    elif goto_param == "previous":
        selected_issue = utils.get_prev_issue(all_issues, current_issue)
    if selected_issue in (None, current_issue):
        # nao precisa redirecionar
        return None
    try:
        url_seg_issue = selected_issue.url_segment
    except AttributeError:
        return None
    else:
        return url_for('main.issue_toc',
                       url_seg=selected_issue.journal.url_segment,
                       url_seg_issue=url_seg_issue)


def get_next_or_previous_issue(current_issue, goto_param):
    if goto_param not in ["next", "previous"]:
        return current_issue

    all_issues = list(
        controllers.get_issues_by_jid(current_issue.journal.id, is_public=True))
    if goto_param == "next":
        return utils.get_next_issue(all_issues, current_issue)
    return utils.get_prev_issue(all_issues, current_issue)


@main.route('/j/<string:url_seg>/aop')
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def aop_toc(url_seg):

    section_filter = request.args.get('section', '', type=str).upper()

    aop_issues = controllers.get_aop_issues(url_seg) or []
    if not aop_issues:
        abort(404, _('Artigos ahead of print não encontrados'))

    goto = request.args.get("goto", None, type=str)
    if goto == "previous":
        url = goto_next_or_previous_issue(aop_issues[-1], goto)
        if url:
            redirect(url, code=301)

    journal = aop_issues[0].journal
    if not journal.is_public:
        abort(404, JOURNAL_UNPUBLISH + _(journal.unpublish_reason))

    utils.fix_journal_last_issue(journal)

    articles = []
    for aop_issue in aop_issues:
        _articles = controllers.get_articles_by_iid(
            aop_issue.iid, is_public=True)
        if _articles:
            articles.extend(_articles)
    if not articles:
        abort(404, _('Artigos ahead of print não encontrados'))

    sections = sorted({a.section.upper() for a in articles if a.section})
    if section_filter != '':
        articles = [a for a in articles if a.section.upper() == section_filter]

    for article in articles:
        article_text_languages = [doc['lang'] for doc in article.htmls]
        article_pdf_languages = [(doc['lang'], doc['url']) for doc in article.pdfs]

        setattr(article, "article_text_languages", article_text_languages)
        setattr(article, "article_pdf_languages", article_pdf_languages)

    context = {
        'this_page_url': url_for("main.aop_toc", url_seg=url_seg),
        'journal': journal,
        'issue': aop_issues[0],
        'issue_bibliographic_strip': "ahead of print",
        'articles': articles,
        'sections': sections,
        'section_filter': section_filter,
        'journal_study_areas': [
            STUDY_AREAS.get(study_area.upper())
            for study_area in journal.study_areas
        ],
        # o primeiro item da lista é o último número.
        'last_issue': journal.last_issue
    }

    return render_template("issue/toc.html", **context)


@main.route('/feed/<string:url_seg>/<string:url_seg_issue>/')
@cache.cached(key_prefix=cache_key_with_lang)
def issue_feed(url_seg, url_seg_issue):
    issue = controllers.get_issue_by_url_seg(url_seg, url_seg_issue)

    if not issue:
        abort(404, _('Número não encontrado'))

    if not issue.is_public:
        abort(404, ISSUE_UNPUBLISH + _(issue.unpublish_reason))

    if not issue.journal.is_public:
        abort(404, JOURNAL_UNPUBLISH + _(issue.journal.unpublish_reason))

    journal = issue.journal
    articles = controllers.get_articles_by_iid(issue.iid, is_public=True)

    feed = AtomFeed(journal.title or "",
                    feed_url=request.url,
                    url=request.url_root,
                    subtitle=utils.get_label_issue(issue))

    feed_language = session.get('lang', get_locale())

    for article in articles:
        # ######### TODO: Revisar #########
        article_lang = feed_language
        if feed_language not in article.languages:
            article_lang = article.original_language

        feed.add(article.title or 'Unknow title',
                 render_template("issue/feed_content.html", article=article),
                 content_type='html',
                 author=article.authors,
                 id=article.doi or article.pid,
                 url=url_external('main.article_detail_v3',
                                  url_seg=journal.url_segment,
                                  article_pid_v3=article.aid,
                                  lang=article_lang),
                 updated=journal.updated,
                 published=journal.created)

    return feed.get_response()

# ##################################Article######################################


@main.route('/article/<regex("S\d{4}-\d{3}[0-9xX][0-2][0-9]{3}\d{4}\d{5}"):pid>/')
@cache.cached(key_prefix=cache_key_with_lang)
def article_detail_pid(pid):

    article = controllers.get_article_by_pid(pid)

    if not article:
        article = controllers.get_article_by_oap_pid(pid)

    if not article:
        abort(404, _('Artigo não encontrado'))

    return redirect(url_for('main.article_detail_v3',
                            url_seg=article.journal.acronym,
                            article_pid_v3=article.aid))


def render_html_from_xml(article, lang, gs_abstract=False):
    logger.debug("Get XML: %s", article.xml)

    if current_app.config["SSM_XML_URL_REWRITE"]:
        result = fetch_data(use_ssm_url(article.xml))
    else:
        result = fetch_data(article.xml)

    xml = etree.parse(BytesIO(result))

    generator = HTMLGenerator.parse(
        xml, valid_only=False, gs_abstract=gs_abstract, output_style="website")

    return generator.generate(lang), generator.languages


def render_html_from_html(article, lang):
    html_url = [html
                for html in article.htmls
                if html['lang'] == lang]

    try:
        html_url = html_url[0]['url']
    except IndexError:
        raise ValueError('Artigo não encontrado') from None

    result = fetch_data(use_ssm_url(html_url))

    html = result.decode('utf8')

    text_languages = [html['lang'] for html in article.htmls]

    return html, text_languages


def render_html_abstract(article, lang):
    abstract_text = ''
    for abstract in article.abstracts:
        if abstract['language'] == lang:
            abstract_text = abstract["text"]
            break
    return abstract_text, article.abstract_languages


def render_html(article, lang, gs_abstract=False):
    if article.xml:
        return render_html_from_xml(article, lang, gs_abstract)
    elif article.htmls:
        if gs_abstract:
            return render_html_abstract(article, lang)
        return render_html_from_html(article, lang)
    else:
        # TODO: Corrigir os teste que esperam ter o atributo ``htmls``
        # O ideal seria levantar um ValueError.
        return '', []


# TODO: Remover assim que o valor Article.xml estiver consistente na base de
# dados
def use_ssm_url(url):
    """Normaliza a string `url` de acordo com os valores das diretivas de
    configuração OPAC_SSM_SCHEME, OPAC_SSM_DOMAIN e OPAC_SSM_PORT.

    A normalização busca obter uma URL absoluta em função de uma relativa, ou
    uma absoluta em função de uma absoluta, mas com as partes *scheme* e
    *authority* trocadas pelas definidas nas diretivas citadas anteriormente.

    Este código deve ser removido assim que o valor de Article.xml estiver
    consistente, i.e., todos os registros possuirem apenas URLs absolutas.
    """
    if url.startswith("http"):
        parsed_url = urlparse(url)
        return current_app.config["SSM_BASE_URI"] + parsed_url.path
    else:
        return current_app.config["SSM_BASE_URI"] + url


@main.route('/article/<string:url_seg>/<string:url_seg_issue>/<string:url_seg_article>/')
@main.route('/article/<string:url_seg>/<string:url_seg_issue>/<string:url_seg_article>/<regex("(?:\w{2})"):lang_code>/')
@main.route('/article/<string:url_seg>/<string:url_seg_issue>/<regex("(.*)"):url_seg_article>/')
@main.route('/article/<string:url_seg>/<string:url_seg_issue>/<regex("(.*)"):url_seg_article>/<regex("(?:\w{2})"):lang_code>/')
@cache.cached(key_prefix=cache_key_with_lang)
def article_detail(url_seg, url_seg_issue, url_seg_article, lang_code=''):
    issue = controllers.get_issue_by_url_seg(url_seg, url_seg_issue)
    if not issue:
        abort(404, _('Issue não encontrado'))

    article = controllers.get_article_by_issue_article_seg(issue.iid, url_seg_article)
    if article is None:
        article = controllers.get_article_by_aop_url_segs(
            issue.journal, url_seg_issue, url_seg_article
        )
    if article is None:
        abort(404, _('Artigo não encontrado'))

    req_params = {
            "url_seg": article.journal.acronym,
            "article_pid_v3": article.aid,
    }
    if lang_code:
        req_params["lang"] = lang_code

    return redirect(url_for('main.article_detail_v3', **req_params))


@main.route('/j/<string:url_seg>/a/<string:article_pid_v3>/')
@main.route('/j/<string:url_seg>/a/<string:article_pid_v3>/<string:part>/')
@cache.cached(key_prefix=cache_key_with_lang)
def article_detail_v3(url_seg, article_pid_v3, part=None):
    qs_lang = request.args.get('lang', type=str) or None
    qs_goto = request.args.get('goto', type=str) or None
    qs_stop = request.args.get('stop', type=str) or None
    qs_format = request.args.get('format', 'html', type=str)


    gs_abstract = (part == "abstract")
    if part and not gs_abstract:
        abort(404,
              _("Não existe '{}'. No seu lugar use '{}'"
                ).format(part, 'abstract'))

    try:
        qs_lang, article = controllers.get_article(
            article_pid_v3, url_seg, qs_lang, gs_abstract, qs_goto)
        if qs_goto:
            return redirect(
                url_for(
                    'main.article_detail_v3',
                    url_seg=url_seg,
                    article_pid_v3=article.aid,
                    part=part,
                    format=qs_format,
                    lang=qs_lang,
                    stop=getattr(article, 'stop', None),
                ),
                code=301
            )
    except (controllers.PreviousOrNextArticleNotFoundError) as e:
        if gs_abstract:
            abort(404, _('Resumo inexistente'))
        abort(404, _('Artigo inexistente'))
    except (controllers.ArticleNotFoundError,
            controllers.ArticleJournalNotFoundError):
        abort(404, _('Artigo não encontrado'))
    except controllers.ArticleLangNotFoundError:
        return redirect(
            url_for(
                'main.article_detail_v3',
                url_seg=url_seg,
                article_pid_v3=article_pid_v3,
                format=qs_format,
            ),
            code=301
        )
    except controllers.ArticleAbstractNotFoundError:
        abort(404, _('Recurso não encontrado'))
    except controllers.ArticleIsNotPublishedError as e:
        abort(404, "{}{}".format(ARTICLE_UNPUBLISH, e))
    except controllers.IssueIsNotPublishedError as e:
        abort(404, "{}{}".format(ISSUE_UNPUBLISH, e))
    except controllers.JournalIsNotPublishedError as e:
        abort(404, "{}{}".format(JOURNAL_UNPUBLISH, e))
    except ValueError as e:
        abort(404, str(e))

    def _handle_html():

        citation_pdf_url = None
        for pdf_data in article.pdfs:
            if pdf_data.get("lang") == qs_lang:
                citation_pdf_url = url_for(
                          'main.article_detail_v3',
                          url_seg=article.journal.url_segment,
                          article_pid_v3=article_pid_v3,
                          lang=qs_lang,
                          format="pdf",
                       )
                break

        website = request.url
        if website:
            parsed_url = urlparse(request.url)
            if current_app.config["FORCE_USE_HTTPS_GOOGLE_TAGS"]:
                website = "{}://{}".format('https', parsed_url.netloc)
            else:
                website = "{}://{}".format(parsed_url.scheme, parsed_url.netloc)
        if citation_pdf_url:
            citation_pdf_url = "{}{}".format(website, citation_pdf_url)
        try:
            html, text_languages = render_html(article, qs_lang, gs_abstract)
        except (ValueError, NonRetryableError):
            abort(404, _('HTML do Artigo não encontrado ou indisponível'))
        except RetryableError:
            abort(500, _('Erro inesperado'))

        text_versions = sorted(
               [
                   (
                       lang,
                       display_original_lang_name(lang),
                       url_for(
                          'main.article_detail_v3',
                          url_seg=article.journal.url_segment,
                          article_pid_v3=article_pid_v3,
                          lang=lang
                       )
                   )
                   for lang in text_languages
               ]
           )
        citation_xml_url = "{}{}".format(
            website,
            url_for(
                'main.article_detail_v3',
                url_seg=article.journal.url_segment,
                article_pid_v3=article_pid_v3,
                format="xml",
                lang=article.original_language,
            )
        )
        context = {
            'next_article': qs_stop != 'next',
            'previous_article': qs_stop != 'previous',
            'article': article,
            'journal': article.journal,
            'issue': article.issue,
            'html': html,
            'citation_pdf_url': citation_pdf_url,
            'citation_xml_url': citation_xml_url,
            'article_lang': qs_lang,
            'text_versions': text_versions,
            'related_links': controllers.related_links(article),
            'gs_abstract': gs_abstract,
            'part': part,
        }
        return render_template("article/detail.html", **context)

    def _handle_pdf():
        if not article.pdfs:
            abort(404, _('PDF do Artigo não encontrado'))

        pdf_info = [pdf for pdf in article.pdfs if pdf['lang'] == qs_lang]
        if len(pdf_info) != 1:
            abort(404, _('PDF do Artigo não encontrado'))

        try:
            pdf_url = pdf_info[0]['url']
        except (IndexError, KeyError, ValueError, TypeError):
            abort(404, _('PDF do Artigo não encontrado'))

        if pdf_url:
            return get_pdf_content(pdf_url)
        raise abort(404, _('Recurso do Artigo não encontrado. Caminho inválido!'))

    def _handle_xml():
        if current_app.config["SSM_XML_URL_REWRITE"]:
            result = fetch_data(use_ssm_url(article.xml))
        else:
            result = fetch_data(article.xml)
        response = make_response(result)
        response.headers['Content-Type'] = 'application/xml'
        return response

    if 'html' == qs_format:
        return _handle_html()
    elif 'pdf' == qs_format:
        return _handle_pdf()
    elif 'xml' == qs_format:
        return _handle_xml()
    else:
        abort(400, _('Formato não suportado'))


@main.route('/readcube/epdf/')
@main.route('/readcube/epdf.php')
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def article_epdf():
    doi = request.args.get('doi', None, type=str)
    pid = request.args.get('pid', None, type=str)
    pdf_path = request.args.get('pdf_path', None, type=str)
    lang = request.args.get('lang', None, type=str)

    if not all([doi, pid, pdf_path, lang]):
        abort(400, _('Parâmetros insuficientes para obter o EPDF do artigo'))
    else:
        context = {
            'doi': doi,
            'pid': pid,
            'pdf_path': pdf_path,
            'lang': lang,
        }
        return render_template("article/epdf.html", **context)


def get_pdf_content(url):
    logger.debug("Get PDF: %s", url)
    if current_app.config["SSM_ARTICLE_ASSETS_OR_RENDITIONS_URL_REWRITE"]:
        url = use_ssm_url(url)
    try:
        response = fetch_data(url)
    except NonRetryableError:
        abort(404, _('PDF não encontrado'))
    except RetryableError:
        abort(500, _('Erro inesperado'))
    else:
        mimetype, __ = mimetypes.guess_type(url)
        return Response(response, mimetype=mimetype)


@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def get_content_from_ssm(resource_ssm_media_path):
    resource_ssm_full_url = current_app.config['SSM_BASE_URI'] + resource_ssm_media_path

    url = resource_ssm_full_url.strip()
    mimetype, __ = mimetypes.guess_type(url)

    try:
        ssm_response = fetch_data(url)
    except NonRetryableError:
        abort(404, _('Recurso não encontrado'))
    except RetryableError:
        abort(500, _('Erro inesperado'))
    else:
        return Response(ssm_response, mimetype=mimetype)


@main.route('/media/assets/<regex("(.*)"):relative_media_path>')
@cache.cached(key_prefix=cache_key_with_lang)
def media_assets_proxy(relative_media_path):
    resource_ssm_path = '{ssm_media_path}{resource_path}'.format(
        ssm_media_path=current_app.config['SSM_MEDIA_PATH'],
        resource_path=relative_media_path)
    return get_content_from_ssm(resource_ssm_path)


@main.route('/article/ssm/content/raw/')
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def article_ssm_content_raw():
    resource_ssm_path = request.args.get('resource_ssm_path', None)
    if not resource_ssm_path:
        raise abort(404, _('Recurso do Artigo não encontrado. Caminho inválido!'))
    else:
        return get_content_from_ssm(resource_ssm_path)


@main.route('/pdf/<string:url_seg>/<string:url_seg_issue>/<string:url_seg_article>')
@main.route('/pdf/<string:url_seg>/<string:url_seg_issue>/<string:url_seg_article>/<regex("(?:\w{2})"):lang_code>')
@main.route('/pdf/<string:url_seg>/<string:url_seg_issue>/<regex("(.*)"):url_seg_article>')
@main.route('/pdf/<string:url_seg>/<string:url_seg_issue>/<regex("(.*)"):url_seg_article>/<regex("(?:\w{2})"):lang_code>')
@cache.cached(key_prefix=cache_key_with_lang)
def article_detail_pdf(url_seg, url_seg_issue, url_seg_article, lang_code=''):
    """
    Padrões esperados:
        `/pdf/csc/2021.v26suppl1/2557-2558`
        `/pdf/csc/2021.v26suppl1/2557-2558/en`
    """
    if not lang_code and "." not in url_seg_issue:
        return router_legacy_pdf(url_seg, url_seg_issue, url_seg_article)

    issue = controllers.get_issue_by_url_seg(url_seg, url_seg_issue)
    if not issue:
        abort(404, _('Issue não encontrado'))

    article = controllers.get_article_by_issue_article_seg(issue.iid, url_seg_article)
    if not article:
        abort(404, _('Artigo não encontrado'))

    req_params = {
        'url_seg': article.journal.url_segment,
        'article_pid_v3': article.aid,
        'format': 'pdf',
    }
    if lang_code:
        req_params['lang'] = lang_code

    return redirect(url_for('main.article_detail_v3', **req_params), code=301)


@main.route('/pdf/<string:journal_acron>/<string:issue_info>/<string:pdf_filename>.pdf')
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def router_legacy_pdf(journal_acron, issue_info, pdf_filename):
    pdf_filename = '%s.pdf' % pdf_filename

    journal = controllers.get_journal_by_url_seg(journal_acron)

    if not journal:
        abort(404, _('Este PDF não existe em http://www.scielo.br. Consulte http://search.scielo.org'))

    article = controllers.get_article_by_pdf_filename(
        journal_acron, issue_info, pdf_filename)

    if not article:
        abort(404, _('PDF do artigo não foi encontrado'))

    return redirect(
        url_for(
            'main.article_detail_v3',
            url_seg=article.journal.url_segment,
            article_pid_v3=article.aid,
            format='pdf',
            lang=article._pdf_lang,
        ),
        code=301
    )

@main.route('/cgi-bin/fbpe/<string:text_or_abstract>/')
@cache.cached(key_prefix=cache_key_with_lang_with_qs)
def router_legacy_article(text_or_abstract):
    pid = request.args.get('pid', None)
    lng = request.args.get('lng', None)
    if not (text_or_abstract in ['fbtext', 'fbabs'] and pid):
        # se tem pid
        abort(400, _('Requsição inválida ao tentar acessar o artigo com pid: %s' % pid))

    article = controllers.get_article_by_pid_v1(pid)
    if not article:
        abort(404, _('Artigo não encontrado'))

    return redirect(
        url_for(
            'main.article_detail_v3',
            url_seg=article.journal.url_segment,
            article_pid_v3=article.aid,
        ),
        code=301
    )


# ###############################E-mail share##################################


@main.route("/email_share_ajax/", methods=['POST'])
def email_share_ajax():

    if not request.is_xhr:
        abort(400, _('Requisição inválida.'))

    form = forms.EmailShareForm(request.form)

    if form.validate():
        recipients = [email.strip() for email in form.data['recipients'].split(';') if email.strip() != '']

        sent, message = controllers.send_email_share(form.data['your_email'],
                                                     recipients,
                                                     form.data['share_url'],
                                                     form.data['subject'],
                                                     form.data['comment'])

        return jsonify({'sent': sent, 'message': str(message),
                        'fields': [key for key in form.data.keys()]})

    else:
        return jsonify({'sent': False, 'message': form.errors,
                        'fields': [key for key in form.data.keys()]})


@main.route("/form_mail/", methods=['GET'])
def email_form():
    context = {'url': request.args.get('url')}
    return render_template("email/email_form.html", **context)


@main.route("/email_error_ajax/", methods=['POST'])
def email_error_ajax():

    if not request.is_xhr:
        abort(400, _('Requisição inválida.'))

    form = forms.ErrorForm(request.form)

    if form.validate():

        recipients = [email.strip() for email in current_app.config.get('EMAIL_ACCOUNTS_RECEIVE_ERRORS') if email.strip() != '']

        sent, message = controllers.send_email_error(form.data['name'],
                                                     form.data['your_email'],
                                                     recipients,
                                                     form.data['url'],
                                                     form.data['error_type'],
                                                     form.data['message'],
                                                     form.data['page_title'])

        return jsonify({'sent': sent, 'message': str(message),
                        'fields': [key for key in form.data.keys()]})

    else:
        return jsonify({'sent': False, 'message': form.errors,
                        'fields': [key for key in form.data.keys()]})


@main.route("/error_mail/", methods=['GET'])
def error_form():
    context = {'url': request.args.get('url')}
    return render_template("includes/error_form.html", **context)


# ###############################Others########################################


@main.route("/media/<path:filename>/", methods=['GET'])
@cache.cached(key_prefix=cache_key_with_lang)
def download_file_by_filename(filename):
    media_root = current_app.config['MEDIA_ROOT']
    return send_from_directory(media_root, filename)


@main.route("/img/scielo.gif", methods=['GET'])
def full_text_image():
    return send_from_directory('static', 'img/full_text_scielo_img.gif')


@main.route("/robots.txt", methods=['GET'])
def get_robots_txt_file():
    return send_from_directory('static', 'robots.txt')


@main.route("/revistas/<path:journal_seg>/<string:page>.htm", methods=['GET'])
def router_legacy_info_pages(journal_seg, page):
    """
    Essa view function realiza o redirecionamento das URLs antigas para as novas URLs.

    Mantém um dicionário como uma tabela relacionamento entre o nome das páginas que pode ser:

       Página      âncora

    [iaboutj.htm, eaboutj.htm, paboutj.htm] -> #about
    [iedboard.htm, eedboard.htm, pedboard.htm] -> #editors
    [iinstruc.htm einstruc.htm, pinstruc.htm]-> #instructions
    isubscrp.htm -> Sem âncora
    """

    page_anchor = {
        'iaboutj': '#about',
        'eaboutj': '#about',
        'paboutj': '#about',
        'eedboard': '#editors',
        'iedboard': '#editors',
        'pedboard': '#editors',
        'iinstruc': '#instructions',
        'pinstruc': '#instructions',
        'einstruc': '#instructions'
        }
    return redirect('%s%s' % (url_for('main.about_journal',
                                      url_seg=journal_seg), page_anchor.get(page, '')), code=301)


@main.route("/api/v1/counter_dict", methods=['GET'])
def router_counter_dicts():
    """
    Essa view function retorna um dicionário, em formato JSON, que mapeia PIDs a insumos
    necessários para o funcionamento das aplicações Matomo & COUNTER & SUSHI.
    """
    end_date = request.args.get('end_date', '', type=str)
    try:
        end_date = datetime.strptime(end_date, '%Y-%m-%d')
    except ValueError:
        end_date = datetime.now()
    begin_date = end_date - timedelta(days=30)

    page = request.args.get('page', type=int)
    if not page:
        page = 1

    limit = request.args.get('limit', type=int)
    if not limit or limit > 100 or limit < 0:
        limit = 100

    results = {'dictionary_date': end_date,
               'end_date': end_date.strftime('%Y-%m-%d %H-%M-%S'),
               'begin_date': begin_date.strftime('%Y-%m-%d %H-%M-%S'),
               'documents': {},
               'collection': current_app.config['OPAC_COLLECTION']}

    articles = controllers.get_articles_by_date_range(begin_date, end_date, page, limit)
    for a in articles.items:
        results['documents'].update(get_article_counter_data(a))

    results['total'] = articles.total
    results['pages'] = articles.pages
    results['limit'] = articles.per_page
    results['page'] = articles.page

    return jsonify(results)


def get_article_counter_data(article):
    return {
        article.aid: {
            "journal_acronym": article.journal.acronym,
            "pid": article.pid if article.pid else '',
            "aop_pid": article.aop_pid if article.aop_pid else '',
            "pid_v1": article.scielo_pids.get('v1', ''),
            "pid_v2": article.scielo_pids.get('v2', ''),
            "pid_v3": article.scielo_pids.get('v3', ''),
            "publication_date": article.publication_date,
            "default_language": article.original_language,
            "create": article.created,
            "update": article.updated
        }
    }


@main.route('/cgi-bin/wxis.exe/iah/')
def author_production():
    # http://www.scielo.br/cgi-bin/wxis.exe/iah/
    # ?IsisScript=iah/iah.xis&base=article%5Edlibrary&format=iso.pft&
    # lang=p&nextAction=lnk&
    # indexSearch=AU&exprSearch=MEIERHOFFER,+LILIAN+KOZSLOWSKI
    # ->
    # //search.scielo.org/?lang=pt&q=au:MEIERHOFFER,+LILIAN+KOZSLOWSKI

    search_url = current_app.config.get('URL_SEARCH')
    if not search_url:
        abort(404, "URL_SEARCH: {}".format(_('Página não encontrada')))

    qs_exprSearch = request.args.get('exprSearch', type=str) or ''
    qs_indexSearch = request.args.get('indexSearch', type=str) or ''
    qs_lang = request.args.get('lang', type=str) or ''

    _lang = IAHX_LANGS.get(qs_lang) or ''
    _lang = _lang and "lang={}".format(_lang)

    _expr = "{}{}".format(
        qs_indexSearch == "AU" and "au:" or '', qs_exprSearch)
    _expr = _expr and "q={}".format(_expr.replace(" ", "+"))

    _and = _lang and _expr and "&" or ''
    _question_mark = (_lang or _expr) and "?" or ""

    if search_url.startswith("//"):
        protocol = "https:"
    elif search_url.startswith("http"):
        protocol = ""
    else:
        protocol = "https://"

    url = "{}{}{}{}{}{}".format(
        protocol, search_url, _question_mark, _lang, _and, _expr)
    return redirect(url, code=301)

[(45, 'logging.getLogger', 'logging.getLogger', (['__name__'], {}), False, 'import logging\n'), (47, 'flask_babelex.gettext', '_', (['"""O periódico está indisponível por motivo de: """'], {}), True, 'from flask_babelex import gettext as _\n'), (48, 'flask_babelex.gettext', '_', (['"""O número está indisponível por motivo de: """'], {}), True, 'from flask_babelex import gettext as _\n'), (49, 'flask_babelex.gettext', '_', (['"""O artigo está indisponível por motivo de: """'], {}), True, 'from flask_babelex import gettext as _\n'), (183, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (230, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (248, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (282, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (337, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (361, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (475, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (537, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (582, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (624, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (645, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (671, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (748, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (800, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (923, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (984, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (1031, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (1128, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (1154, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (1322, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (1356, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (1374, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (1383, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (1396, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (1426, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (1453, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang_with_qs'}), False, 'from webapp import cache\n'), (1547, 'webapp.cache.cached', 'cache.cached', ([], {'key_prefix': 'cache_key_with_lang'}), False, 'from webapp import cache\n'), (59, 'flask.url_for', 'url_for', (['endpoint'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (60, 'urllib.parse.urljoin', 'urljoin', (['request.url_root', 'url'], {}), False, 'from urllib.parse import urljoin\n'), (140, 'flask.current_app.config.get', 'current_app.config.get', (['"""LANGUAGES"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (156, 'flask.current_app.config.get', 'current_app.config.get', (['"""LANGUAGES"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (162, 'flask.request.args.get', 'request.args.get', (['"""hash"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (168, 'flask.redirect', 'redirect', (['referrer'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (186, 'webapp.controllers.get_latest_news_by_lang', 'controllers.get_latest_news_by_lang', (['language'], {}), False, 'from webapp import controllers\n'), (188, 'webapp.controllers.get_collection_tweets', 'controllers.get_collection_tweets', ([], {}), False, 'from webapp import controllers\n'), (189, 'webapp.controllers.get_press_releases', 'controllers.get_press_releases', (["{'language': language}"], {}), False, 'from webapp import controllers\n'), (223, 'flask.render_template', 'render_template', (['"""collection/index.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (233, 'flask.request.args.get', 'request.args.get', (['"""status"""', '""""""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (243, 'flask.render_template', 'render_template', (['"""collection/list_journal.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (257, 'flask.request.args.get', 'request.args.get', (['"""status"""', '""""""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (258, 'flask.request.args.get', 'request.args.get', (['"""query"""', '""""""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (259, 'flask.request.args.get', 'request.args.get', (['"""filter"""', '"""areas"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (268, 'webapp.controllers.get_journals_grouped_by', 'controllers.get_journals_grouped_by', (['thematic_table[thematic_filter]', 'title_query'], {'query_filter': 'query_filter', 'lang': 'lang'}), False, 'from webapp import controllers\n'), (275, 'flask.render_template', 'render_template', (['"""collection/list_thematic.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (285, 'webapp.controllers.get_current_collection', 'controllers.get_current_collection', ([], {}), False, 'from webapp import controllers\n'), (288, 'flask_babelex.gettext', '_', (["('10 últimos periódicos inseridos na coleção %s' % collection.name)"], {}), True, 'from flask_babelex import gettext as _\n'), (290, 'werkzeug.contrib.atom.AtomFeed', 'AtomFeed', (['title'], {'subtitle': 'subtitle', 'feed_url': 'request.url', 'url': 'request.url_root'}), False, 'from werkzeug.contrib.atom import AtomFeed\n'), (294, 'webapp.controllers.get_journals_paginated', 'controllers.get_journals_paginated', ([], {'title_query': '""""""', 'page': '(1)', 'order_by': '"""-created"""', 'per_page': '(10)'}), False, 'from webapp import controllers\n'), (354, 'flask.render_template', 'render_template', (['"""collection/about.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (364, 'flask.request.args.get', 'request.args.get', (['"""script"""', 'None'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (365, 'flask.request.args.get', 'request.args.get', (['"""pid"""', 'None'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (366, 'flask.request.args.get', 'request.args.get', (['"""tlng"""', 'None'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (477, 'webapp.controllers.get_journal_by_url_seg', 'controllers.get_journal_by_url_seg', (['url_seg'], {}), False, 'from webapp import controllers\n'), (485, 'webapp.utils.utils.fix_journal_last_issue', 'utils.fix_journal_last_issue', (['journal'], {}), False, 'from webapp.utils import utils\n'), (489, 'webapp.controllers.get_latest_news_by_lang', 'controllers.get_latest_news_by_lang', (['language'], {}), False, 'from webapp import controllers\n'), (492, 'webapp.controllers.get_press_releases', 'controllers.get_press_releases', (["{'journal': journal, 'language': language}"], {}), False, 'from webapp import controllers\n'), (515, 'webapp.controllers.get_journal_metrics', 'controllers.get_journal_metrics', (['journal'], {}), False, 'from webapp import controllers\n'), (533, 'flask.render_template', 'render_template', (['"""journal/detail.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (539, 'webapp.controllers.get_journal_by_url_seg', 'controllers.get_journal_by_url_seg', (['url_seg'], {}), False, 'from webapp import controllers\n'), (547, 'webapp.controllers.get_issues_by_jid', 'controllers.get_issues_by_jid', (['journal.jid'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (549, 'webapp.controllers.get_articles_by_iid', 'controllers.get_articles_by_iid', (['last_issue.iid'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (586, 'webapp.controllers.get_journal_by_url_seg', 'controllers.get_journal_by_url_seg', (['url_seg'], {}), False, 'from webapp import controllers\n'), (594, 'webapp.utils.utils.fix_journal_last_issue', 'utils.fix_journal_last_issue', (['journal'], {}), False, 'from webapp.utils import utils\n'), (604, 'webapp.controllers.get_page_by_journal_acron_lang', 'controllers.get_page_by_journal_acron_lang', (['journal.acronym', 'language'], {}), False, 'from webapp import controllers\n'), (620, 'flask.render_template', 'render_template', (['"""journal/about.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (630, 'flask.request.args.get', 'request.args.get', (['"""query"""', '""""""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (631, 'flask.request.args.get', 'request.args.get', (['"""query_filter"""', '""""""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (632, 'flask.request.args.get', 'request.args.get', (['"""page"""', '(1)'], {'type': 'int'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (635, 'webapp.controllers.get_alpha_list_from_paginated_journals', 'controllers.get_alpha_list_from_paginated_journals', ([], {'title_query': 'query', 'query_filter': 'query_filter', 'page': 'page', 'lang': 'lang'}), False, 'from webapp import controllers\n'), (641, 'flask.jsonify', 'jsonify', (['response_data'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (651, 'flask.request.args.get', 'request.args.get', (['"""query"""', '""""""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (652, 'flask.request.args.get', 'request.args.get', (['"""query_filter"""', '""""""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (653, 'flask.request.args.get', 'request.args.get', (['"""filter"""', '"""areas"""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (667, 'flask.jsonify', 'jsonify', (['objects'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (699, 'webapp.utils.utils.is_recaptcha_valid', 'utils.is_recaptcha_valid', (['request'], {}), False, 'from webapp.utils import utils\n'), (729, 'webapp.controllers.get_journal_by_url_seg', 'controllers.get_journal_by_url_seg', (['url_seg'], {}), False, 'from webapp import controllers\n'), (736, 'flask.render_template', 'render_template', (['"""journal/includes/contact_form.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (750, 'webapp.controllers.get_journal_by_url_seg', 'controllers.get_journal_by_url_seg', (['url_seg'], {}), False, 'from webapp import controllers\n'), (762, 'webapp.controllers.get_issues_for_grid_by_jid', 'controllers.get_issues_for_grid_by_jid', (['journal.id'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (784, 'flask.render_template', 'render_template', (['"""issue/grid.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (803, 'flask.request.args.get', 'request.args.get', (['"""goto"""', 'None'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (819, 'webapp.controllers.get_issue_by_url_seg', 'controllers.get_issue_by_url_seg', (['url_seg', 'url_seg_issue'], {}), False, 'from webapp import controllers\n'), (831, 'webapp.utils.utils.fix_journal_last_issue', 'utils.fix_journal_last_issue', (['journal'], {}), False, 'from webapp.utils import utils\n'), (840, 'webapp.controllers.get_articles_by_iid', 'controllers.get_articles_by_iid', (['issue.iid'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (885, 'flask.render_template', 'render_template', (['"""issue/toc.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (919, 'webapp.utils.utils.get_prev_issue', 'utils.get_prev_issue', (['all_issues', 'current_issue'], {}), False, 'from webapp.utils import utils\n'), (932, 'flask.request.args.get', 'request.args.get', (['"""goto"""', 'None'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (942, 'webapp.utils.utils.fix_journal_last_issue', 'utils.fix_journal_last_issue', (['journal'], {}), False, 'from webapp.utils import utils\n'), (980, 'flask.render_template', 'render_template', (['"""issue/toc.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (986, 'webapp.controllers.get_issue_by_url_seg', 'controllers.get_issue_by_url_seg', (['url_seg', 'url_seg_issue'], {}), False, 'from webapp import controllers\n'), (998, 'webapp.controllers.get_articles_by_iid', 'controllers.get_articles_by_iid', (['issue.iid'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (1034, 'webapp.controllers.get_article_by_pid', 'controllers.get_article_by_pid', (['pid'], {}), False, 'from webapp import controllers\n'), (1057, 'packtools.HTMLGenerator.parse', 'HTMLGenerator.parse', (['xml'], {'valid_only': '(False)', 'gs_abstract': 'gs_abstract', 'output_style': '"""website"""'}), False, 'from packtools import HTMLGenerator\n'), (1130, 'webapp.controllers.get_issue_by_url_seg', 'controllers.get_issue_by_url_seg', (['url_seg', 'url_seg_issue'], {}), False, 'from webapp import controllers\n'), (1134, 'webapp.controllers.get_article_by_issue_article_seg', 'controllers.get_article_by_issue_article_seg', (['issue.iid', 'url_seg_article'], {}), False, 'from webapp import controllers\n'), (1159, 'flask.request.args.get', 'request.args.get', (['"""format"""', '"""html"""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1324, 'flask.request.args.get', 'request.args.get', (['"""doi"""', 'None'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1325, 'flask.request.args.get', 'request.args.get', (['"""pid"""', 'None'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1326, 'flask.request.args.get', 'request.args.get', (['"""pdf_path"""', 'None'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1327, 'flask.request.args.get', 'request.args.get', (['"""lang"""', 'None'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1361, 'mimetypes.guess_type', 'mimetypes.guess_type', (['url'], {}), False, 'import mimetypes\n'), (1385, 'flask.request.args.get', 'request.args.get', (['"""resource_ssm_path"""', 'None'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1406, 'webapp.controllers.get_issue_by_url_seg', 'controllers.get_issue_by_url_seg', (['url_seg', 'url_seg_issue'], {}), False, 'from webapp import controllers\n'), (1410, 'webapp.controllers.get_article_by_issue_article_seg', 'controllers.get_article_by_issue_article_seg', (['issue.iid', 'url_seg_article'], {}), False, 'from webapp import controllers\n'), (1430, 'webapp.controllers.get_journal_by_url_seg', 'controllers.get_journal_by_url_seg', (['journal_acron'], {}), False, 'from webapp import controllers\n'), (1435, 'webapp.controllers.get_article_by_pdf_filename', 'controllers.get_article_by_pdf_filename', (['journal_acron', 'issue_info', 'pdf_filename'], {}), False, 'from webapp import controllers\n'), (1455, 'flask.request.args.get', 'request.args.get', (['"""pid"""', 'None'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1456, 'flask.request.args.get', 'request.args.get', (['"""lng"""', 'None'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1461, 'webapp.controllers.get_article_by_pid_v1', 'controllers.get_article_by_pid_v1', (['pid'], {}), False, 'from webapp import controllers\n'), (1484, 'webapp.forms.EmailShareForm', 'forms.EmailShareForm', (['request.form'], {}), False, 'from webapp import forms\n'), (1506, 'flask.render_template', 'render_template', (['"""email/email_form.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1515, 'webapp.forms.ErrorForm', 'forms.ErrorForm', (['request.form'], {}), False, 'from webapp import forms\n'), (1540, 'flask.render_template', 'render_template', (['"""includes/error_form.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1550, 'flask.send_from_directory', 'send_from_directory', (['media_root', 'filename'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1555, 'flask.send_from_directory', 'send_from_directory', (['"""static"""', '"""img/full_text_scielo_img.gif"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1560, 'flask.send_from_directory', 'send_from_directory', (['"""static"""', '"""robots.txt"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1599, 'flask.request.args.get', 'request.args.get', (['"""end_date"""', '""""""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1606, 'flask.request.args.get', 'request.args.get', (['"""page"""'], {'type': 'int'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1610, 'flask.request.args.get', 'request.args.get', (['"""limit"""'], {'type': 'int'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1620, 'webapp.controllers.get_articles_by_date_range', 'controllers.get_articles_by_date_range', (['begin_date', 'end_date', 'page', 'limit'], {}), False, 'from webapp import controllers\n'), (1629, 'flask.jsonify', 'jsonify', (['results'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1658, 'flask.current_app.config.get', 'current_app.config.get', (['"""URL_SEARCH"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1685, 'flask.redirect', 'redirect', (['url'], {'code': '(301)'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (78, 'requests.get', 'requests.get', (['url'], {'timeout': 'timeout'}), False, 'import requests\n'), (123, 'webapp.forms.EmailShareForm', 'forms.EmailShareForm', ([], {}), False, 'from webapp import forms\n'), (124, 'webapp.forms.ContactForm', 'forms.ContactForm', ([], {}), False, 'from webapp import forms\n'), (125, 'webapp.forms.ErrorForm', 'forms.ErrorForm', ([], {}), False, 'from webapp import forms\n'), (149, 'flask.current_app.config.get', 'current_app.config.get', (['"""BABEL_DEFAULT_LOCALE"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (239, 'webapp.controllers.get_journal_json_data', 'controllers.get_journal_json_data', (['journal'], {}), False, 'from webapp import controllers\n'), (303, 'webapp.controllers.get_issues_by_jid', 'controllers.get_issues_by_jid', (['journal.jid'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (311, 'collections.OrderedDict', 'OrderedDict', ([], {}), False, 'from collections import OrderedDict\n'), (345, 'webapp.controllers.get_page_by_slug_name', 'controllers.get_page_by_slug_name', (['slug_name', 'language'], {}), False, 'from webapp import controllers\n'), (351, 'webapp.controllers.get_pages_by_lang', 'controllers.get_pages_by_lang', (['language'], {}), False, 'from webapp import controllers\n'), (470, 'flask.url_for', 'url_for', (['"""main.journal_detail"""'], {'url_seg': 'journal_seg'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (500, 'webapp.controllers.get_recent_articles_of_issue', 'controllers.get_recent_articles_of_issue', (['journal.last_issue.iid'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (657, 'webapp.controllers.get_journals_grouped_by', 'controllers.get_journals_grouped_by', (['"""study_areas"""', 'query'], {'query_filter': 'query_filter', 'lang': 'lang'}), False, 'from webapp import controllers\n'), (701, 'webapp.forms.ContactForm', 'forms.ContactForm', (['request.form'], {}), False, 'from webapp import forms\n'), (703, 'webapp.controllers.get_journal_by_url_seg', 'controllers.get_journal_by_url_seg', (['url_seg'], {}), False, 'from webapp import controllers\n'), (744, 'flask.url_for', 'url_for', (['"""main.issue_grid"""'], {'url_seg': 'url_seg'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (793, 'flask.url_for', 'url_for', (['"""main.issue_toc"""'], {'url_seg': 'url_seg', 'url_seg_issue': 'url_seg_issue'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (835, 'flask.request.args.get', 'request.args.get', (['"""goto"""', 'None'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (837, 'flask.redirect', 'redirect', (['goto_url'], {'code': '(301)'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (869, 'flask.url_for', 'url_for', (['"""main.issue_toc"""'], {'url_seg': 'url_seg', 'url_seg_issue': 'url_seg_issue'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (893, 'webapp.controllers.get_issues_by_jid', 'controllers.get_issues_by_jid', (['current_issue.journal.id'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (895, 'webapp.utils.utils.get_next_issue', 'utils.get_next_issue', (['all_issues', 'current_issue'], {}), False, 'from webapp.utils import utils\n'), (906, 'flask.url_for', 'url_for', (['"""main.issue_toc"""'], {'url_seg': 'selected_issue.journal.url_segment', 'url_seg_issue': 'url_seg_issue'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (916, 'webapp.controllers.get_issues_by_jid', 'controllers.get_issues_by_jid', (['current_issue.journal.id'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (918, 'webapp.utils.utils.get_next_issue', 'utils.get_next_issue', (['all_issues', 'current_issue'], {}), False, 'from webapp.utils import utils\n'), (928, 'webapp.controllers.get_aop_issues', 'controllers.get_aop_issues', (['url_seg'], {}), False, 'from webapp import controllers\n'), (946, 'webapp.controllers.get_articles_by_iid', 'controllers.get_articles_by_iid', (['aop_issue.iid'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (965, 'flask.url_for', 'url_for', (['"""main.aop_toc"""'], {'url_seg': 'url_seg'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1037, 'webapp.controllers.get_article_by_oap_pid', 'controllers.get_article_by_oap_pid', (['pid'], {}), False, 'from webapp import controllers\n'), (1042, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {'url_seg': 'article.journal.acronym', 'article_pid_v3': 'article.aid'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1055, 'io.BytesIO', 'BytesIO', (['result'], {}), False, 'from io import BytesIO\n'), (1118, 'urllib.parse.urlparse', 'urlparse', (['url'], {}), False, 'from urllib.parse import urlparse\n'), (1136, 'webapp.controllers.get_article_by_aop_url_segs', 'controllers.get_article_by_aop_url_segs', (['issue.journal', 'url_seg_issue', 'url_seg_article'], {}), False, 'from webapp import controllers\n'), (1149, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1156, 'flask.request.args.get', 'request.args.get', (['"""lang"""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1157, 'flask.request.args.get', 'request.args.get', (['"""goto"""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1158, 'flask.request.args.get', 'request.args.get', (['"""stop"""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1169, 'webapp.controllers.get_article', 'controllers.get_article', (['article_pid_v3', 'url_seg', 'qs_lang', 'gs_abstract', 'qs_goto'], {}), False, 'from webapp import controllers\n'), (1282, 'flask.render_template', 'render_template', (['"""article/detail.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1306, 'flask.make_response', 'make_response', (['result'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1338, 'flask.render_template', 'render_template', (['"""article/epdf.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1352, 'mimetypes.guess_type', 'mimetypes.guess_type', (['url'], {}), False, 'import mimetypes\n'), (1353, 'flask.Response', 'Response', (['response'], {'mimetype': 'mimetype'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1370, 'flask.Response', 'Response', (['ssm_response'], {'mimetype': 'mimetype'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1422, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1442, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {'url_seg': 'article.journal.url_segment', 'article_pid_v3': 'article.aid', 'format': '"""pdf"""', 'lang': 'article._pdf_lang'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1466, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {'url_seg': 'article.journal.url_segment', 'article_pid_v3': 'article.aid'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1489, 'webapp.controllers.send_email_share', 'controllers.send_email_share', (["form.data['your_email']", 'recipients', "form.data['share_url']", "form.data['subject']", "form.data['comment']"], {}), False, 'from webapp import controllers\n'), (1505, 'flask.request.args.get', 'request.args.get', (['"""url"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1521, 'webapp.controllers.send_email_error', 'controllers.send_email_error', (["form.data['name']", "form.data['your_email']", 'recipients', "form.data['url']", "form.data['error_type']", "form.data['message']", "form.data['page_title']"], {}), False, 'from webapp import controllers\n'), (1539, 'flask.request.args.get', 'request.args.get', (['"""url"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1601, 'datetime.datetime.strptime', 'datetime.strptime', (['end_date', '"""%Y-%m-%d"""'], {}), False, 'from datetime import datetime, timedelta\n'), (1604, 'datetime.timedelta', 'timedelta', ([], {'days': '(30)'}), False, 'from datetime import datetime, timedelta\n'), (1662, 'flask.request.args.get', 'request.args.get', (['"""exprSearch"""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1663, 'flask.request.args.get', 'request.args.get', (['"""indexSearch"""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1664, 'flask.request.args.get', 'request.args.get', (['"""lang"""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (102, 'webapp.controllers.get_current_collection', 'controllers.get_current_collection', ([], {}), False, 'from webapp import controllers\n'), (143, 'flask.session.keys', 'session.keys', ([], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (159, 'flask_babelex.gettext', '_', (['"""Código de idioma inválido"""'], {}), True, 'from flask_babelex import gettext as _\n'), (179, 'flask.current_app.config.get', 'current_app.config.get', (['"""BABEL_DEFAULT_LOCALE"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (240, 'webapp.controllers.get_journals', 'controllers.get_journals', ([], {'query_filter': 'query_filter'}), False, 'from webapp import controllers\n'), (287, 'flask_babelex.gettext', '_', (['"""Últimos periódicos inseridos na coleção"""'], {}), True, 'from flask_babelex import gettext as _\n'), (308, 'webapp.controllers.get_articles_by_iid', 'controllers.get_articles_by_iid', (['last_issue.iid'], {'is_public': '(True)'}), False, 'from webapp import controllers\n'), (325, 'flask.render_template', 'render_template', (['"""collection/list_feed_content.html"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (372, 'flask_babelex.gettext', '_', (["(u'Requsição inválida ao tentar acessar o artigo com pid: %s' % pid)"], {}), True, 'from flask_babelex import gettext as _\n'), (464, 'flask.redirect', 'redirect', (['"""/"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (480, 'flask_babelex.gettext', '_', (['"""Periódico não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (542, 'flask_babelex.gettext', '_', (['"""Periódico não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (554, 'webapp.utils.utils.get_label_issue', 'utils.get_label_issue', (['last_issue'], {}), False, 'from webapp.utils import utils\n'), (567, 'flask.render_template', 'render_template', (['"""issue/feed_content.html"""'], {'article': 'article'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (589, 'flask_babelex.gettext', '_', (['"""Periódico não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (628, 'flask_babelex.gettext', '_', (['"""Requisição inválida. Deve ser por ajax"""'], {}), True, 'from flask_babelex import gettext as _\n'), (649, 'flask_babelex.gettext', '_', (['"""Requisição inválida. Deve ser por ajax"""'], {}), True, 'from flask_babelex import gettext as _\n'), (659, 'webapp.controllers.get_journals_grouped_by', 'controllers.get_journals_grouped_by', (['"""subject_categories"""', 'query'], {'query_filter': 'query_filter', 'lang': 'lang'}), False, 'from webapp import controllers\n'), (674, 'flask_babelex.gettext', '_', (['"""Parámetro "extension" é inválido, deve ser "csv" ou "xls"."""'], {}), True, 'from flask_babelex import gettext as _\n'), (682, 'flask.request.args.get', 'request.args.get', (['"""query"""', '""""""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (688, 'flask.Response', 'Response', (['data'], {'mimetype': 'mimetype'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (697, 'flask_babelex.gettext', '_', (['"""Requisição inválida, deve ser ajax."""'], {}), True, 'from flask_babelex import gettext as _\n'), (711, 'webapp.controllers.send_email_contact', 'controllers.send_email_contact', (['recipients', "form.data['name']", "form.data['your_email']", "form.data['message']"], {}), False, 'from webapp import controllers\n'), (724, 'flask_babelex.gettext', '_', (['"""Requisição inválida, captcha inválido."""'], {}), True, 'from flask_babelex import gettext as _\n'), (731, 'flask_babelex.gettext', '_', (['"""Periódico não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (753, 'flask_babelex.gettext', '_', (['"""Periódico não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (790, 'flask.url_for', 'url_for', (['"""main.aop_toc"""'], {'url_seg': 'url_seg'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (809, 'flask.url_for', 'url_for', (['"""main.aop_toc"""'], {'url_seg': 'url_seg'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (821, 'flask_babelex.gettext', '_', (['"""Número não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (897, 'webapp.utils.utils.get_prev_issue', 'utils.get_prev_issue', (['all_issues', 'current_issue'], {}), False, 'from webapp.utils import utils\n'), (926, 'flask.request.args.get', 'request.args.get', (['"""section"""', '""""""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (930, 'flask_babelex.gettext', '_', (['"""Artigos ahead of print não encontrados"""'], {}), True, 'from flask_babelex import gettext as _\n'), (936, 'flask.redirect', 'redirect', (['url'], {'code': '(301)'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (951, 'flask_babelex.gettext', '_', (['"""Artigos ahead of print não encontrados"""'], {}), True, 'from flask_babelex import gettext as _\n'), (989, 'flask_babelex.gettext', '_', (['"""Número não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1003, 'webapp.utils.utils.get_label_issue', 'utils.get_label_issue', (['issue'], {}), False, 'from webapp.utils import utils\n'), (1014, 'flask.render_template', 'render_template', (['"""issue/feed_content.html"""'], {'article': 'article'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1040, 'flask_babelex.gettext', '_', (['"""Artigo não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1132, 'flask_babelex.gettext', '_', (['"""Issue não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1140, 'flask_babelex.gettext', '_', (['"""Artigo não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1228, 'urllib.parse.urlparse', 'urlparse', (['request.url'], {}), False, 'from urllib.parse import urlparse\n'), (1259, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {'url_seg': 'article.journal.url_segment', 'article_pid_v3': 'article_pid_v3', 'format': '"""xml"""', 'lang': 'article.original_language'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1278, 'webapp.controllers.related_links', 'controllers.related_links', (['article'], {}), False, 'from webapp import controllers\n'), (1299, 'flask_babelex.gettext', '_', (['"""Recurso do Artigo não encontrado. Caminho inválido!"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1330, 'flask_babelex.gettext', '_', (['"""Parâmetros insuficientes para obter o EPDF do artigo"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1387, 'flask_babelex.gettext', '_', (['"""Recurso do Artigo não encontrado. Caminho inválido!"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1408, 'flask_babelex.gettext', '_', (['"""Issue não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1412, 'flask_babelex.gettext', '_', (['"""Artigo não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1433, 'flask_babelex.gettext', '_', (['"""Este PDF não existe em http://www.scielo.br. Consulte http://search.scielo.org"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1439, 'flask_babelex.gettext', '_', (['"""PDF do artigo não foi encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1459, 'flask_babelex.gettext', '_', (["('Requsição inválida ao tentar acessar o artigo com pid: %s' % pid)"], {}), True, 'from flask_babelex import gettext as _\n'), (1463, 'flask_babelex.gettext', '_', (['"""Artigo não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1482, 'flask_babelex.gettext', '_', (['"""Requisição inválida."""'], {}), True, 'from flask_babelex import gettext as _\n'), (1513, 'flask_babelex.gettext', '_', (['"""Requisição inválida."""'], {}), True, 'from flask_babelex import gettext as _\n'), (1603, 'datetime.datetime.now', 'datetime.now', ([], {}), False, 'from datetime import datetime, timedelta\n'), (209, 'opac_schema.v1.models.Journal.objects.filter', 'Journal.objects.filter', ([], {'is_public': '(True)', 'current_status': '"""current"""'}), False, 'from opac_schema.v1.models import Journal, Issue, Article, Collection\n'), (212, 'opac_schema.v1.models.Article.objects.filter', 'Article.objects.filter', ([], {'is_public': '(True)'}), False, 'from opac_schema.v1.models import Journal, Issue, Article, Collection\n'), (300, 'datetime.datetime.now', 'datetime.now', ([], {}), False, 'from datetime import datetime, timedelta\n'), (347, 'flask_babelex.gettext', '_', (['"""Página não encontrada"""'], {}), True, 'from flask_babelex import gettext as _\n'), (377, 'webapp.controllers.get_journal_by_issn', 'controllers.get_journal_by_issn', (['pid'], {}), False, 'from webapp import controllers\n'), (483, 'flask_babelex.gettext', '_', (['journal.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (545, 'flask_babelex.gettext', '_', (['journal.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (566, 'flask_babelex.gettext', '_', (['"""Artigo sem título"""'], {}), True, 'from flask_babelex import gettext as _\n'), (592, 'flask_babelex.gettext', '_', (['journal.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (661, 'webapp.controllers.get_journals_grouped_by', 'controllers.get_journals_grouped_by', (['"""publisher_name"""', 'query'], {'query_filter': 'query_filter', 'lang': 'lang'}), False, 'from webapp import controllers\n'), (676, 'flask_babelex.gettext', '_', (['"""Parámetro "list_type" é inválido, deve ser: "alpha", "areas", "wos" ou "publisher"."""'], {}), True, 'from flask_babelex import gettext as _\n'), (706, 'flask_babelex.gettext', '_', (['"""Periódico não permite envio de email."""'], {}), True, 'from flask_babelex import gettext as _\n'), (756, 'flask_babelex.gettext', '_', (['journal.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (816, 'flask.request.args.get', 'request.args.get', (['"""section"""', '""""""'], {'type': 'str'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (823, 'flask_babelex.gettext', '_', (['issue.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (828, 'flask_babelex.gettext', '_', (['journal.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (940, 'flask_babelex.gettext', '_', (['journal.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (992, 'flask_babelex.gettext', '_', (['issue.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (995, 'flask_babelex.gettext', '_', (['issue.journal.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (1187, 'flask_babelex.gettext', '_', (['"""Artigo inexistente"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1190, 'flask_babelex.gettext', '_', (['"""Artigo não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1193, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {'url_seg': 'url_seg', 'article_pid_v3': 'article_pid_v3', 'format': 'qs_format'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1202, 'flask_babelex.gettext', '_', (['"""Recurso não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1217, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {'url_seg': 'article.journal.url_segment', 'article_pid_v3': 'article_pid_v3', 'lang': 'qs_lang', 'format': '"""pdf"""'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1286, 'flask_babelex.gettext', '_', (['"""PDF do Artigo não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1290, 'flask_babelex.gettext', '_', (['"""PDF do Artigo não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1348, 'flask_babelex.gettext', '_', (['"""PDF não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1350, 'flask_babelex.gettext', '_', (['"""Erro inesperado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1366, 'flask_babelex.gettext', '_', (['"""Recurso não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1368, 'flask_babelex.gettext', '_', (['"""Erro inesperado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1519, 'flask.current_app.config.get', 'current_app.config.get', (['"""EMAIL_ACCOUNTS_RECEIVE_ERRORS"""'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1589, 'flask.url_for', 'url_for', (['"""main.about_journal"""'], {'url_seg': 'journal_seg'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1660, 'flask_babelex.gettext', '_', (['"""Página não encontrada"""'], {}), True, 'from flask_babelex import gettext as _\n'), (133, 'flask.current_app.config.get', 'current_app.config.get', (['"""SCIELO_ORG_URIS"""', '{}'], {}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (385, 'flask.url_for', 'url_for', (['"""main.journal_detail"""'], {'url_seg': 'journal.url_segment'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (390, 'webapp.controllers.get_issue_by_pid', 'controllers.get_issue_by_pid', (['pid'], {}), False, 'from webapp import controllers\n'), (686, 'datetime.datetime.now', 'datetime.now', ([], {}), False, 'from datetime import datetime, timedelta\n'), (1165, 'flask_babelex.gettext', '_', (['"""Não existe \'{}\'. No seu lugar use \'{}\'"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1186, 'flask_babelex.gettext', '_', (['"""Resumo inexistente"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1238, 'flask_babelex.gettext', '_', (['"""HTML do Artigo não encontrado ou indisponível"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1240, 'flask_babelex.gettext', '_', (['"""Erro inesperado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1246, 'webapp.config.lang_names.display_original_lang_name', 'display_original_lang_name', (['lang'], {}), False, 'from webapp.config.lang_names import display_original_lang_name\n'), (1247, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {'url_seg': 'article.journal.url_segment', 'article_pid_v3': 'article_pid_v3', 'lang': 'lang'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (1295, 'flask_babelex.gettext', '_', (['"""PDF do Artigo não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (1317, 'flask_babelex.gettext', '_', (['"""Formato não suportado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (380, 'flask_babelex.gettext', '_', (['"""Periódico não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (406, 'flask.url_for', 'url_for', (['"""main.issue_toc"""'], {'url_seg': 'issue.journal.url_segment', 'url_seg_issue': 'issue.url_segment'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (414, 'webapp.controllers.get_article_by_pid_v2', 'controllers.get_article_by_pid_v2', (['pid'], {}), False, 'from webapp import controllers\n'), (665, 'flask_babelex.gettext', '_', (['"""Parámetro "filter" é inválido, deve ser "areas", "wos" ou "publisher"."""'], {}), True, 'from flask_babelex import gettext as _\n'), (383, 'flask_babelex.gettext', '_', (['journal.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (393, 'flask_babelex.gettext', '_', (['"""Número não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (403, 'flask.url_for', 'url_for', (['"""main.aop_toc"""'], {'url_seg': 'url_seg'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (424, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {'url_seg': 'article.journal.url_segment', 'article_pid_v3': 'article.aid', 'part': 'part', 'lang': 'tlng'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (433, 'webapp.controllers.get_journal_by_issn', 'controllers.get_journal_by_issn', (['pid'], {}), False, 'from webapp import controllers\n'), (396, 'flask_babelex.gettext', '_', (['issue.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (399, 'flask_babelex.gettext', '_', (['issue.journal.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (416, 'flask_babelex.gettext', '_', (['"""Artigo não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (441, 'flask.url_for', 'url_for', (['"""main.issue_grid"""'], {'url_seg': 'journal.url_segment'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (446, 'webapp.controllers.get_article_by_pid_v2', 'controllers.get_article_by_pid_v2', (['pid'], {}), False, 'from webapp import controllers\n'), (436, 'flask_babelex.gettext', '_', (['"""Periódico não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n'), (451, 'flask.url_for', 'url_for', (['"""main.article_detail_v3"""'], {'url_seg': 'article.journal.url_segment', 'article_pid_v3': 'article.aid', 'format': '"""pdf"""'}), False, 'from flask import render_template, abort, current_app, request, session, redirect, jsonify, url_for, Response, send_from_directory, g, make_response\n'), (461, 'flask_babelex.gettext', '_', (["(u'Requsição inválida ao tentar acessar o artigo com pid: %s' % pid)"], {}), True, 'from flask_babelex import gettext as _\n'), (439, 'flask_babelex.gettext', '_', (['journal.unpublish_reason'], {}), True, 'from flask_babelex import gettext as _\n'), (448, 'flask_babelex.gettext', '_', (['"""Artigo não encontrado"""'], {}), True, 'from flask_babelex import gettext as _\n')]