#!/usr/bin/env python
#
# Data Quality Checker also known as DQC
#
# Read the README.md for more detailed information
#
#       Barcelona Supercomputing Center - Centro Nacional de Supercomputacion
#       Earth Sciences Department - Computational Earth Sciences
#     
#     Authors: 
#       Joan Sala Calero (joan.sala@bsc.es)

import os
from textwrap import wrap
import configparser
from io import StringIO
from datetime import date

from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch, cm
from reportlab.pdfbase.pdfmetrics import registerFont

# Header and footer (official C3S)
imgdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'img')

# Register official C3S font
fontdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'font')
registerFont(TTFont('Calibri', os.path.join(fontdir, 'Calibri.ttf')))

"""
Convert a txt to a pdf file (reporting)
"""
def line_breaks(text, chars_per_line=160):
	ls = ''
	for t in text.split('\n'):
		pieces = wrap(t, chars_per_line)
		for p in pieces:
			ls = ls + p + '\n'
	return ls

"""
Convert a txt to a pdf file (reporting)
"""
def save_txt_report(txt_file, pdf_file):

	# PDF report name
	print('INFO: Saving report to {}'.format(pdf_file))

	# Read content (detailed txt file messages)
	with open(txt_file, 'r') as f:
		txt_str = f.read()

	# Line breaks
	txt_str = line_breaks(txt_str)

	# Write PDF
	try:
		# Init
		c = canvas.Canvas(pdf_file)
		break_into_pages(txt_str, c, 80, 'Detailed log output', True)
		# Save
		c.save()
	except:
		raise Exception('Could not convert txt to pdf. Check directory permissions')

"""
Convert a ini to a pdf file (reporting)
"""
def save_pdf_report(testname, res_file, log_file):

	# PDF report name
	pdf_file = res_file.replace('.ini', '-{}.pdf'.format(testname))
	print('INFO: Saving report to {}'.format(pdf_file))

	# Read+Filter content (result/config)
	res_str = filter_config(res_file, testname)

	# Read content (detailed log file messages)
	log_str = ''
	with open(log_file, 'r') as f2:
		log_str = f2.read()
		log_str = filter_page(testname, log_str)

	# Write PDF
	try:
		# Init		
		c = canvas.Canvas(pdf_file)
		
		# Write 2 sections	
		break_into_pages(line_breaks(res_str), c, 80, '1. Summary of data checks', False)
		break_into_pages(line_breaks(log_str), c, 80, '2. Detailed log output', True)
		
		# Save
		c.save()		
	except:
		raise Exception('Could not convert ini to pdf. Check directory permissions')

	return pdf_file

"""
Filter a config object
"""
def filter_config(res_file, testname):
	cf = configparser.ConfigParser()
	cf.read(res_file)

	for s in cf.sections():
		# Remove log (unnecessary for CMS)
		if 'log' in cf[s]:
			cf[s].pop('log')

		# Remove section (if not relevant for testXX)
		if not(testname in s):
			cf.remove_section(s)
	
	res_str = StringIO()		
	cf.write(res_str)
	return res_str.getvalue()	

"""
Filter page (by test name)
"""
def filter_page(s, page_str):
	out_str = ''
	s1 = s.replace('-', '_')
	s2 = s.replace('_', '-')

	for l in page_str.splitlines():	
		iden = l.split(':')[0]

		if 'not implemented yet' in l:
			continue

		if s1 in iden or s2 in iden or s in iden:
			out_str += (l + '\n')
	return out_str


"""
Init PDF page (body)
"""
def init_page(c, font_size=6):

	# Normal text prepare
	t = c.beginText()
	t.setFillColorRGB(0, 0, 0)
	t.setFont('Calibri', font_size)
	t.setCharSpace(0.5)
	t.setTextOrigin(40, 700)
	return t

"""
Init PDF page (title)
"""
def init_title(c, font_size=9):

	# TITLE text prepare - #941333
	t = c.beginText()
	t.setFillColorRGB(0.58, 0.075, 0.2)
	t.setFont('Calibri', font_size)
	t.setCharSpace(0.5)
	t.setTextOrigin(40, 725)
	return t

"""
Write PDF page
"""
def write_page(c, body, title, title_str):

	# Header
	c.drawInlineImage(os.path.join(imgdir, "header.png"), 0, 755, height=1.2*inch, width=8.5*inch)

	# Text (title + body)
	title.textLine(title_str)
	c.drawText(title)
	c.drawText(body)

	# Footer
	c.drawImage(os.path.join(imgdir, "footer.png"), 0, 0, mask='auto', height=1.7*inch, width=8.5*inch)

	# Finalize
	c.showPage()

	return init_title(c), init_page(c)

"""
Get page title/section
"""
def get_page_title(log_page, tit, page_count):

	if log_page:
		return tit + ' (page {})'.format(page_count)
	else:
		return tit + ' (generated on {})'.format(date.today())

"""
Write a string into pages
"""
def break_into_pages(txtstr, c, lines_per_page, tit, log_page):

	title = init_title(c)
	body = init_page(c)
	count_lines = 0
	page_count = 1

	for l in txtstr.split('\n'):
		body.textLine(l)
		if count_lines == lines_per_page:
			title, body = write_page(c, body, title, get_page_title(log_page, tit, page_count))
			count_lines = 0
			page_count += 1
		else:
			count_lines+=1

	# Last page
	if count_lines != 0:
		write_page(c, body, title, get_page_title(log_page, tit, page_count))

