# Copyright (c) 2015 - present Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import codecs
import datetime
import itertools
import operator
import os
import re
import sys

try:
    from lxml import etree
except ImportError:
    etree = None

from . import colorize, config, source, utils


ISSUE_KIND_ERROR = 'ERROR'
ISSUE_KIND_WARNING = 'WARNING'
ISSUE_KIND_INFO = 'INFO'
ISSUE_KIND_ADVICE = 'ADVICE'
ISSUE_KIND_LIKE = 'LIKE'

# field names in rows of json reports
JSON_INDEX_DOTTY = 'dotty'
JSON_INDEX_FILENAME = 'file'
JSON_INDEX_HASH = 'hash'
JSON_INDEX_INFER_SOURCE_LOC = 'infer_source_loc'
JSON_INDEX_ISL_FILE = 'file'
JSON_INDEX_ISL_LNUM = 'lnum'
JSON_INDEX_ISL_CNUM = 'cnum'
JSON_INDEX_ISL_ENUM = 'enum'
JSON_INDEX_KIND = 'kind'
JSON_INDEX_LINE = 'line'
JSON_INDEX_PROCEDURE = 'procedure'
JSON_INDEX_PROCEDURE_ID = 'procedure_id'
JSON_INDEX_QUALIFIER = 'qualifier'
JSON_INDEX_QUALIFIER_TAGS = 'qualifier_tags'
JSON_INDEX_TYPE = 'bug_type'
JSON_INDEX_TRACE = 'bug_trace'
JSON_INDEX_TRACE_LEVEL = 'level'
JSON_INDEX_TRACE_FILENAME = 'filename'
JSON_INDEX_TRACE_LINE = 'line_number'
JSON_INDEX_TRACE_COLUMN = 'column_number'
JSON_INDEX_TRACE_DESCRIPTION = 'description'
JSON_INDEX_TRACEVIEW_ID = 'traceview_id'
JSON_INDEX_VISIBILITY = 'visibility'


ISSUE_TYPES_URL = 'http://fbinfer.com/docs/infer-issue-types.html#'


def text_of_infer_loc(loc):
    return ' ({}:{}:{}-{}:)'.format(
        loc[JSON_INDEX_ISL_FILE],
        loc[JSON_INDEX_ISL_LNUM],
        loc[JSON_INDEX_ISL_CNUM],
        loc[JSON_INDEX_ISL_ENUM],
    )


def text_of_report(report):
    filename = report[JSON_INDEX_FILENAME]
    kind = report[JSON_INDEX_KIND]
    line = report[JSON_INDEX_LINE]
    error_type = report[JSON_INDEX_TYPE]
    msg = report[JSON_INDEX_QUALIFIER]
    infer_loc = ''
    if JSON_INDEX_INFER_SOURCE_LOC in report:
        infer_loc = text_of_infer_loc(report[JSON_INDEX_INFER_SOURCE_LOC])
    return '%s:%d: %s: %s%s\n  %s' % (
        filename,
        line,
        kind.lower(),
        error_type,
        infer_loc,
        msg,
    )


def _text_of_report_list(project_root, reports, bugs_txt_path, limit=None,
                         console_out=False,
                         formatter=colorize.TERMINAL_FORMATTER):
    n_issues = len(reports)
    if n_issues == 0:
        msg = 'No issues found'
        if formatter == colorize.TERMINAL_FORMATTER:
            msg = colorize.color('  %s  ' % msg,
                                 colorize.SUCCESS, formatter)
        if console_out:
            utils.stderr(msg)
        return msg


    text_errors_list = []
    for report in reports[:limit]:
        filename = report[JSON_INDEX_FILENAME]
        line = report[JSON_INDEX_LINE]

        source_context = ''
        source_context = source.build_source_context(
            os.path.join(project_root, filename),
            formatter,
            line,
            1,
            True
        )
        indenter = source.Indenter() \
                         .indent_push() \
                         .add(source_context)
        source_context = '\n' + unicode(indenter)

        msg = text_of_report(report)
        if report[JSON_INDEX_KIND] == ISSUE_KIND_ERROR:
            msg = colorize.color(msg, colorize.ERROR, formatter)
        elif report[JSON_INDEX_KIND] == ISSUE_KIND_WARNING:
            msg = colorize.color(msg, colorize.WARNING, formatter)
        elif report[JSON_INDEX_KIND] == ISSUE_KIND_ADVICE:
            msg = colorize.color(msg, colorize.ADVICE, formatter)
        elif report[JSON_INDEX_KIND] == ISSUE_KIND_LIKE:
            msg = colorize.color(msg, colorize.LIKE, formatter)
        text = '%s%s' % (msg, source_context)