#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import argparse
from datetime import date
import importlib

from pymisp import MISPEvent
from defang import defang
from pytaxonomies import Taxonomies


class ReportGenerator():
    def __init__(self, profile="daily_report"):
        self.taxonomies = Taxonomies()
        self.report = ''
        profile_name = "profiles.{}".format(profile)
        self.template = importlib.import_module(name=profile_name)

    def from_remote(self, event_id):
        from pymisp import PyMISP
        from keys import misp_url, misp_key, misp_verifycert
        misp = PyMISP(misp_url, misp_key, misp_verifycert)
        result = misp.get(event_id)
        self.misp_event = MISPEvent()
        self.misp_event.load(result)

    def from_file(self, path):
        self.misp_event = MISPEvent()
        self.misp_event.load_file(path)

    def attributes(self):
        if not self.misp_event.attributes:
            return ''
        list_attributes = []
        for attribute in self.misp_event.attributes:
            if attribute.type in self.template.types_to_attach:
                list_attributes.append("* {}".format(defang(attribute.value)))
        for obj in self.misp_event.Object:
            if obj.name in self.template.objects_to_attach:
                for attribute in obj.Attribute:
                    if attribute.type in self.template.types_to_attach:
                        list_attributes.append("* {}".format(defang(attribute.value)))
        return self.template.attributes.format(list_attributes="\n".join(list_attributes))

    def _get_tag_info(self, machinetag):
        return self.taxonomies.revert_machinetag(machinetag)

    def report_headers(self):
        content = {'org_name': 'name',
                   'date': date.today().isoformat()}
        self.report += self.template.headers.format(**content)

    def event_level_tags(self):
        if not self.misp_event.Tag:
            return ''
        for tag in self.misp_event.Tag:
            # Only look for TLP for now
            if tag['name'].startswith('tlp'):
                tax, predicate = self._get_tag_info(tag['name'])
                return self.template.event_level_tags.format(value=predicate.predicate.upper(), expanded=predicate.expanded)

    def title(self):
        internal_id = ''
        summary = ''
        # Get internal refs for report
        for obj in self.misp_event.Object:
            if obj.name != 'report':
                continue
            for a in obj.Attribute:
                if a.object_relation == 'case-number':
                    internal_id = a.value
                if a.object_relation == 'summary':
                    summary = a.value

        return self.template.title.format(internal_id=internal_id, title=self.misp_event.info,
                                          summary=summary)

    def asciidoc(self, lang='en'):
        self.report += self.title()
        self.report += self.event_level_tags()
        self.report += self.attributes()


if __name__ == '__main__':
    try:
        parser = argparse.ArgumentParser(description='Create a human-readable report out of a MISP event')
        parser.add_argument("--profile", default="daily_report", help="Profile template to use")
        parser.add_argument("-o", "--output", help="Output file to write to (generally ends in .adoc)")
        group = parser.add_mutually_exclusive_group(required=True)
        group.add_argument("-e", "--event", default=[], nargs='+', help="Event ID to get.")
        group.add_argument("-p", "--path", default=[], nargs='+', help="Path to the JSON dump.")

        args = parser.parse_args()

        report = ReportGenerator(args.profile)
        report.report_headers()

        if args.event:
            for eid in args.event:
                report.from_remote(eid)
                report.asciidoc()
        else:
            for f in args.path:
                report.from_file(f)
                report.asciidoc()

        if args.output:
            with open(args.output, "w") as ofile:
                ofile.write(report.report)
        else:
            print(report.report)
    except ModuleNotFoundError as err:
        print(err)