__author__ = "Johannes Köster"
__copyright__ = "Copyright 2015, Johannes Köster"
__email__ = "koester@jimmy.harvard.edu"
__license__ = "MIT"

import time
import csv
import json
from collections import defaultdict

import snakemake.jobs

fmt_time = time.ctime


class Stats:
    def __init__(self):
        self.starttime = dict()
        self.endtime = dict()

    def report_job_start(self, job):
        self.starttime[job] = time.time()

    def report_job_end(self, job):
        self.endtime[job] = time.time()

    @property
    def rule_stats(self):
        runtimes = defaultdict(list)
        for job, t in self.starttime.items():
            runtimes[job.rule].append(self.endtime[job] - t)
        for rule, runtimes in runtimes.items():
            yield (rule, sum(runtimes) / len(runtimes), min(runtimes),
                   max(runtimes))

    @property
    def file_stats(self):
        for job, t in self.starttime.items():
            for f in job.expanded_output:
                start, stop = t, self.endtime[job]
                yield f, fmt_time(start), fmt_time(stop), stop - start, job

    @property
    def overall_runtime(self):
        if self.starttime and self.endtime:
            return max(self.endtime.values()) - min(self.starttime.values())
        else:
            return 0

    def to_json(self, path):
        rule_stats = {
            rule.name: {
                "mean-runtime": mean_runtime,
                "min-runtime": min_runtime,
                "max-runtime": max_runtime
            }
            for rule, mean_runtime, min_runtime, max_runtime in self.rule_stats
        }
        file_stats = {
            f: {
                "start-time": start,
                "stop-time": stop,
                "duration": duration,
                "priority": job.priority
                if job.priority != snakemake.jobs.Job.HIGHEST_PRIORITY else
                "highest",
                "resources": job.resources_dict
            }
            for f, start, stop, duration, job in self.file_stats
        }

        with open(path, "w") as f:
            json.dump({
                "total_runtime": self.overall_runtime,
                "rules": rule_stats,
                "files": file_stats
            }, f,
                      indent=4)
