import os
import yaml

from core import plugintools
from core import constants
from core.searchtools import SearchDef
from core.issues.issue_utils import IssueEntry

LAUNCHPAD = "launchpad"
MASTER_YAML_KNOWN_BUGS_KEY = "bugs-detected"
KNOWN_BUGS = {MASTER_YAML_KNOWN_BUGS_KEY: []}


class BugSearchDef(SearchDef):
    def __init__(self, pattern, bug_id, hint, reason,
                 reason_format_result_groups=None):
        """
        @param reason: string reason describing the issue and why it has been
        flagged. This string can be a template i.e. containing {} fields that
        can be rendered using results.
        @param reason_format_result_groups: if the reason string is a template,
        this is a list of indexes in the results that can be extracted for
        inclusion in the reason.
        """
        super().__init__(pattern, tag=bug_id, hint=hint)
        self._reason = reason
        if reason is None:
            self._reason = ""

        self.reason_format_result_groups = reason_format_result_groups

    @property
    def reason(self):
        return self._reason

    def rendered_reason(self, search_result):
        if self._reason and self.reason_format_result_groups:
            values = []
            for idx in self.reason_format_result_groups:
                values.append(search_result.get(idx))

            return self._reason.format(*values)

        return self._reason


def _get_known_bugs():
    """
    Fetch the current plugin known_bugs.yaml if it exists and return its
    contents or None if it doesn't exist yet.
    """
    if not os.path.isdir(constants.PLUGIN_TMP_DIR):
        raise Exception("plugin tmp dir  '{}' not found".
                        format(constants.PLUGIN_TMP_DIR))

    known_bugs_yaml = os.path.join(constants.PLUGIN_TMP_DIR, "known_bugs.yaml")
    if not os.path.exists(known_bugs_yaml):
        return {}

    bugs = yaml.safe_load(open(known_bugs_yaml))
    if bugs and bugs.get(MASTER_YAML_KNOWN_BUGS_KEY):
        return bugs

    return {}


def add_known_bug(bug_id, description=None, type=LAUNCHPAD):
    """
    Fetch the current plugin known_bugs.yaml if it exists and add new bug with
    description of the bug.
    """
    if not os.path.isdir(constants.PLUGIN_TMP_DIR):
        raise Exception("plugin tmp dir  '{}' not found".
                        format(constants.PLUGIN_TMP_DIR))

    if type == LAUNCHPAD:
        new_bug = "https://bugs.launchpad.net/bugs/{}".format(bug_id)

    if description is None:
        description = "no description provided"

    entry = IssueEntry(new_bug, description, key="id")
    current = _get_known_bugs()
    if current and current.get(MASTER_YAML_KNOWN_BUGS_KEY):
        current[MASTER_YAML_KNOWN_BUGS_KEY].append(entry.data)
    else:
        current = {MASTER_YAML_KNOWN_BUGS_KEY: [entry.data]}

    known_bugs_yaml = os.path.join(constants.PLUGIN_TMP_DIR, "known_bugs.yaml")
    with open(known_bugs_yaml, 'w') as fd:
        fd.write(yaml.dump(current))


def add_known_bugs_to_master_plugin():
    """
    Fetch the current plugin known_bugs.yaml and add it to the master yaml.
    Note that this can only be called once per plugin and is typically
    performed as a final part after all others have executed.
    """
    bugs = _get_known_bugs()
    if bugs and bugs.get(MASTER_YAML_KNOWN_BUGS_KEY):
        plugintools.save_part(bugs, priority=99)

[((56, 22, 56, 79), 'os.path.join', 'os.path.join', ({(56, 35, 56, 59): 'constants.PLUGIN_TMP_DIR', (56, 61, 56, 78): '"""known_bugs.yaml"""'}, {}), "(constants.PLUGIN_TMP_DIR, 'known_bugs.yaml')", False, 'import os\n'), ((82, 12, 82, 54), 'core.issues.issue_utils.IssueEntry', 'IssueEntry', (), '', False, 'from core.issues.issue_utils import IssueEntry\n'), ((89, 22, 89, 79), 'os.path.join', 'os.path.join', ({(89, 35, 89, 59): 'constants.PLUGIN_TMP_DIR', (89, 61, 89, 78): '"""known_bugs.yaml"""'}, {}), "(constants.PLUGIN_TMP_DIR, 'known_bugs.yaml')", False, 'import os\n'), ((52, 11, 52, 50), 'os.path.isdir', 'os.path.isdir', ({(52, 25, 52, 49): 'constants.PLUGIN_TMP_DIR'}, {}), '(constants.PLUGIN_TMP_DIR)', False, 'import os\n'), ((57, 11, 57, 42), 'os.path.exists', 'os.path.exists', ({(57, 26, 57, 41): 'known_bugs_yaml'}, {}), '(known_bugs_yaml)', False, 'import os\n'), ((72, 11, 72, 50), 'os.path.isdir', 'os.path.isdir', ({(72, 25, 72, 49): 'constants.PLUGIN_TMP_DIR'}, {}), '(constants.PLUGIN_TMP_DIR)', False, 'import os\n'), ((102, 8, 102, 48), 'core.plugintools.save_part', 'plugintools.save_part', (), '', False, 'from core import plugintools\n'), ((91, 17, 91, 35), 'yaml.dump', 'yaml.dump', ({(91, 27, 91, 34): 'current'}, {}), '(current)', False, 'import yaml\n')]