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)

[((1781, 1838), 'os.path.join', 'os.path.join', (['constants.PLUGIN_TMP_DIR', '"""known_bugs.yaml"""'], {}), "(constants.PLUGIN_TMP_DIR, 'known_bugs.yaml')\n", (1793, 1838), False, 'import os\n'), ((2581, 2623), 'core.issues.issue_utils.IssueEntry', 'IssueEntry', (['new_bug', 'description'], {'key': '"""id"""'}), "(new_bug, description, key='id')\n", (2591, 2623), False, 'from core.issues.issue_utils import IssueEntry\n'), ((2873, 2930), 'os.path.join', 'os.path.join', (['constants.PLUGIN_TMP_DIR', '"""known_bugs.yaml"""'], {}), "(constants.PLUGIN_TMP_DIR, 'known_bugs.yaml')\n", (2885, 2930), False, 'import os\n'), ((1601, 1640), 'os.path.isdir', 'os.path.isdir', (['constants.PLUGIN_TMP_DIR'], {}), '(constants.PLUGIN_TMP_DIR)\n', (1614, 1640), False, 'import os\n'), ((1850, 1881), 'os.path.exists', 'os.path.exists', (['known_bugs_yaml'], {}), '(known_bugs_yaml)\n', (1864, 1881), False, 'import os\n'), ((2237, 2276), 'os.path.isdir', 'os.path.isdir', (['constants.PLUGIN_TMP_DIR'], {}), '(constants.PLUGIN_TMP_DIR)\n', (2250, 2276), False, 'import os\n'), ((3368, 3408), 'core.plugintools.save_part', 'plugintools.save_part', (['bugs'], {'priority': '(99)'}), '(bugs, priority=99)\n', (3389, 3408), False, 'from core import plugintools\n'), ((2991, 3009), 'yaml.dump', 'yaml.dump', (['current'], {}), '(current)\n', (3000, 3009), False, 'import yaml\n')]