import sys
from pathlib import Path
import yaml
from pyppl.plugin import hookimpl, pypplPostRunFunc
from pyppl.logger import logger
from pyppl.utils import fs, Box
from pyppl.exception import ProcAttributeError
from .report import Report

__version__ = "0.0.1"

@hookimpl
def setup(config):
	config['report'] = ''

@hookimpl
def procSetAttr(proc, name, value):
	if name == 'report' and value.startswith('file:'):
		scriptpath = Path(value[5:])
		if not scriptpath.is_absolute():
			from inspect import getframeinfo, stack

			# 0: .../pyppl-report/pyppl-report/__init__.py
			# 1: .../pluggy/callers.py
			# 2: .../pluggy/manager.py
			# 3: .../pluggy/manager.py
			# 4: .../pluggy/hooks.py
			# 5: .../PyPPL/pyppl/proc.py
			# 6: /file/define/the/report
			# if it fails in the future, check if the callstacks changed from pluggy
			caller = getframeinfo(stack()[6][0])
			scriptdir = Path(caller.filename).parent.resolve()
			scriptpath = scriptdir / scriptpath
		if not scriptpath.is_file():
			raise ProcAttributeError(
				'Report template file does not exist: %s' % scriptpath)
		proc.config[name] = "file:%s" % scriptpath
		return True

@hookimpl
def procGetAttr(proc, name):
	"""Pre-calculate the attribute"""
	if name == 'report':
		return Path(proc.workdir) / 'proc.report'

@hookimpl
def procPostRun(proc):
	"""Generate report for the process"""
	fs.remove(proc.report)
	if not proc.config.report:
		return

	logger.debug('Rendering report template ...')
	report = proc.config.report
	if report.startswith ('file:'):
		tplfile = Path(report[5:])
		if not fs.exists (tplfile):
			raise ProcAttributeError(tplfile, 'No such report template file')
		logger.debug("Using report template: %s", tplfile, proc = proc.id)
		report = tplfile.read_text()

	report  = proc.template(report, **proc.tplenvs)
	rptdata = Box(jobs = [], **proc.procvars)
	for job in proc.jobs:
		jobdata  = job.data
		datafile = job.dir / 'output' / 'job.report.data.yaml'
		data = {}
		data.update(jobdata.job)
		if datafile.is_file():
			data.update(yaml.safe_load(str(datafile)))
		rptdata.jobs.append(Box(i = jobdata.i, o = jobdata.o, **data))
	proc.report.write_text(report.render(rptdata))

def pyppl_report(ppl, outfile = None,
	title = 'A report generated by pipeline powered by PyPPL.',
	standalone = True, template = False, filters = False):
	"""@API
	Generate report for the pipeline.
	Currently only HTML format supported.
	@params:
		outfile (file): The report file.
		title (str): The title of the report.
			- Default: 'A report generated by pipeline powered by PyPPL.'
		standalone (bool): A standalone html file? Default: True
	@returns:
		(PyPPL): The pipeline object itppl.
	"""
	outfile = outfile or (Path('.') / Path(sys.artv[0]).stem).with_suffix(
		'%s.report.html' % ('.' + str(ppl.counter) if ppl.counter else ''))
	logger.report('Generating report using pandoc ...')
	reports = [proc.report for proc in ppl.procs if proc.report.exists()]
	cmd = Report(reports, outfile, title).generate(standalone, template, filters)
	logger.report('Command: ' + cmd.cmd)
	if cmd.rc == 0:
		logger.report('Report generated: ' + str(outfile))
	else:
		logger.error(cmd.stderr)
		sys.exit(1)

@hookimpl
def pypplRegisterPreRunFunc(ppl):
	pypplPostRunFunc(ppl, 'report', pyppl_report)
