import json
import io
import orthanc
import base64
import pdfkit
from pdfkit import configuration
from pdfkit import from_string

# PDF Python Plug-in Utility for Orthanc (see https://www.orthanc-server.com/)
# Converts raw HTML (escaped) into a base64 encoded PDF format and optionally return the base64 via the REST call and/or attaches the PDF to a study by study uuid.
# Accepts a base64 encoded document (the raw base64 beginning with JVER) and attaches it to a study by study uuid.
# Sorry about the long curl examples, but useful for testing.

# Copyright (C) 2020 Stephen D. Scotti, MD, sscotti@sscotti.org, SIAS.

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# A plain text version of the GNU license can be found here:  https://www.gnu.org/licenses/gpl-3.0.txt

# Format for Server Error in response from Orthanc.
# HttpError	"Internal Server Error"
# HttpStatus	500
# Message	"Error encountered within the plugin engine"
# Method	"POST"
# OrthancError	"Error encountered within the plugin engine"
# OrthancStatus	1
# Uri	"/pdfkit/htmltopdf"

# BEGINNING OF PDF FROM HTML
# REQUIRES pdfkit python module, can be installed with python3 -m pip install pdfkit
# REQUIRES wkhtmltopdf.  There are various ways to install that:  e.g. https://computingforgeeks.com/install-wkhtmltopdf-on-ubuntu-debian-linux/
# The path has to be defined in the code below:  see config = pdfkit.configuration(wkhtmltopdf=bytes("/usr/local/bin/wkhtmltopdf", 'utf-8')), on UBUNTU might be in usr/bin.
# Should be easy to test after adding the dependencies and editing the Orthanc Config file:

#  "Plugins" : [
#  "libOrthancPython.mainline.dylib"
#  ],

# "PythonScript" : "pdfhtmlpython.py",
# "PythonVerbose" : true,

#  Sample curl call to attach a report to a study.

# curl -k http://localhost:8042/pdfkit/htmltopdf -d '{"method":"base64","html":"","title":"BASE64 TO PDF","studyuuid":"e6596260-fdf91aa9-0257a3c2-4778ebda-f2d56d1b","base64":"","return":1,"attach":1}'
# method is base64 or html
# html is the esacped raw html code, including style sheets, if it is an html method.
# title is the title for the document
# studyuuid is the uuid for the parent study to attach to
# base64 is the base64 encoded string for a pdf document to attach (beginning with JVER)
# return is a flag to return the base64 endoding (for the html conversion if you don't want it attached)
# attach is a flag to attach to the studyuuid.


# curl -k http://localhost:8042/pdfkit/htmltopdf -d '{"html":"<style>.htmlmarkup, #reportswrapper > div {padding:10px;margin:0px;background: white;color: #000;font-family: \"Trebuchet MS\", Helvetica, sans-serif;font-size: 12px;font-weight:bold;}#markupform .htmlmarkup {background:black !important;color:white;}.htmlmarkup div, #reportswrapper > div div {display:block;padding:0px;line-height: initial;margin:5px 0px 5px 0px;}.htmlmarkup label, #reportswrapper > div label{font-size: 14px;color:#000;font-weight:bold;padding-right:10px;}.htmlmarkup section > header, #reportswrapper > div section > header{color: #000;font-family: \"Trebuchet MS\", Helvetica, sans-serif;font-size: 16px;font-weight: bold;margin-bottom: 0.0cm;margin-top: 0.3cm;}.htmlmarkup section > section > header, #reportswrapper > div section > section > header{color: #000;font-family: \"Trebuchet MS\", Helvetica, sans-serif;font-size: 12px;font-weight: bold;margin-bottom: 0.0cm;margin-top: 0.3cm;text-align: left;}.htmlmarkup section > section > section > header, #reportswrapper > div section > section > section > header{color: #000;font-family: \"Trebuchet MS\", Helvetica, sans-serif;font-size: 12px;font-weight: bold;margin-bottom: 0.0cm;margin-top: 0.3cm;text-align: left;}.htmlmarkup > section{}.htmlmarkup section > section, #reportswrapper > div section > section{padding-left: 0.8cm;}.htmlmarkup p, #reportswrapper > div p{margin-bottom: 0.0cm;margin-top: 0.0cm;padding-left: 0.8cm;}reportswrapper {width:100%;}#header_info {margin: 20px auto 10px auto;width:100%;;}#header_info, #header_info td {border: 1px solid black;border-collapse: collapse;background:#DDD;font-size: 12px;font-weight: bold;padding: 2px 5px 2px 5px;}#header_info tr:nth-child(even) td {background:#FFF !important;}#disclaimer {margin:20px 10px 0px 10px;text-align: justify;font-size: 8px;}#header_info > tbody > tr > td:first-child {width:350px;}#header_info > tbody > tr > td:nth-child(2){width:250px;}#header_info > tbody > tr > td:nth-child(3){width:190px;}.htmlmarkup, #reportswrapper {width:800px}#reportbody{font-size:12px;width: 90%;word-wrap: break-word;}#sigblock{margin-top:10px;}#apiresults {line-height: normal;font-size: 16px;font-family: PoppinsRegular;color: black;background: #FFF;border-radius: 20px;padding: 20px 10px 20px 10px;border: 2px solid black;width:816px;}\r\n<\/style>\r\n<style>\r\n#reportheader{position:relative;width:800px;border: 3px solid black;padding: 5px 5px 20px 5px;margin: 0px 0px 10px 0px;box-shadow: 2px 2px 2px #000;text-align:center;overflow:auto;margin:auto;}#reportheader #logo {height:60px;border:none;position:absolute;left:0;right:0;margin:auto;}#reportheader #floatleft{width:350px;display:inline-block;text-align:left;float: left;}#reportheader #floatright{width:max-content;text-align:left;float: right;padding-right:10px;}.letterheadlabel {display:inline-block;width:60px;text-align:right;margin-right:5px;}\r\n<\/style><div id=\"reportheader\"><div><img id=\"logo\" src=\"https:\/\/www.sias.dev\/images\/reportslogo.png\" alt=\"sitelogo\"><div id=\"floatleft\">Cayman Medical Ltd.<br>71 Eastern Ave<br>P.O. Box 32322<br>George Town, Cayman Islands KY1-1209 <\/div><div id=\"floatright\"><span class=\"letterheadlabel\">Phone:  <\/span>KY 000-000-0000<br><span class=\"letterheadlabel\">Fax:  <\/span>KY 000-000-0000<br><span class=\"letterheadlabel\">Email:  <\/span>roland@talanow.info<br><span class=\"letterheadlabel\">Website:  <\/span>medpics.com<br><\/div><\/div><\/div><div id=\"reportnoheader\"><table id=\"header_info\">\r\n\t\t<tbody><tr>\r\n\t\t\t<td id=\"report_name\"> Patient Name: Scotti, Stephen<\/td>\r\n\t\t\t<td id=\"report_mrn\"> Med Rec Number:  DEV0000001<\/td>\r\n\t\t\t<td rowspan=\"6\" style=\"vertical-align:text-top;white-space:break-spaces;width:200px\">Indication:  test<\/td>\r\n\t\t<\/tr>\r\n\t\t<tr>\r\n\t\t\t<td> DOB: Nov-16-1957<\/td>\r\n\t\t\t<td> Sex: M<\/td>\r\n\t\t<\/tr>\r\n\t<tr>\r\n\t<td> Accession Number:  DEVACC00000001<\/td>\r\n\t<td> Date of Exam:  Apr-23-2020 11:10:59<\/td>\r\n<\/tr>\r\n\t<tr><td> Referring Physician:  0001, SCOTTI, STEPHEN, D<\/td>\r\n\t<td> Referring Physician ID:  0001<\/td>\r\n<\/tr>\r\n<tr>\r\n\t<td> Interpreting Radiologist:  Stephen Douglas Scotti M.D.<br>Interpreting Radiologist Profile ID:1<\/td>\r\n\t<td> Report Generated:  Jul-05-2020 18:39:46<\/td>\r\n<\/tr>\r\n\r\n<tr>\r\n\t<td colspan=\"2\"> Read Status:  FINAL<\/td>\r\n<\/tr>\r\n<\/tbody><\/table><div class=\"htmlmarkup\" name=\"htmlmarkup\"><section><header>MR <span style=\"DISPLAY:INLINE-BLOCK\">RIGHT<\/span> ANKLE<\/header><p><span style=\"display:inline-block\">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<\/span><\/p><\/section><section><header>CLINICAL INFORMATION<\/header><p><span style=\"display:inline-block\">test<\/span><\/p><\/section><section><header>COMPARISON<\/header><p><span style=\"display:inline-block\">None. <\/span><\/p><\/section><section><header>FINDINGS<\/header><p><label>Alignment:<\/label><span>Normal. <\/span><\/p><section><header>MEDIAL COMPARTMENT<\/header><p><label>Medial malleolus:<\/label><span>Normal. <\/span><\/p><p><label>Posterior tibial tendon:<\/label><span>Normal. <\/span><\/p><p><label>Flexor digitorum longus tendon:<\/label><span>Normal. <\/span><\/p><p><label>Deltoid ligament complex (superficial):<\/label><span>Normal. <\/span><\/p><p><label>Deltoid ligament complex (deep):<\/label><span>Normal. <\/span><\/p><p><label>Spring ligament:<\/label><span>Normal. <\/span><\/p><\/section><section><header>LATERAL COMPARTMENT<\/header><p><label>Lateral malleolus:<\/label><span>Normal. <\/span><\/p><p><label>Retromalleolar groove:<\/label><span style=\"display:inline-block\">Flat<\/span><\/p><p><label>Peroneus longus tendon:<\/label><span>Normal. <\/span><\/p><p><label>Peroneus brevis tendon:<\/label><span>Normal. <\/span><\/p><p><label>Peroneal retinaculum:<\/label><span>Normal. <\/span><\/p><p><label>Peroneus quartus:<\/label><span>Absent. <\/span><\/p><p><label>Anterior inferior tibiofibular ligament:<\/label><span>Normal. <\/span><\/p><p><label>Posterior inferior tibiofibular ligament:<\/label><span>Normal. <\/span><\/p><p><label>Anterior talofibular ligament:<\/label><span>Normal. <\/span><\/p><p><label>Calcaneofibular ligament:<\/label><span>Normal. <\/span><\/p><p><label>Posterior talofibular ligament<\/label><span>Normal. <\/span><\/p><\/section><section><header>POSTERIOR COMPARTMENT<\/header><p><label>Posterior talus:<\/label><span>Normal. <\/span><\/p><p><label>Flexor hallucis longus:<\/label><span>Normal. <\/span><\/p><p><label>Intermalleolar ligament:<\/label><span>Normal. <\/span><\/p><p><label>Achilles tendon:<\/label><span>Normal. <\/span><\/p><p><label>Plantar fascia:<\/label><span>Normal. <\/span><\/p><\/section><section><header>ARTICULATIONS<\/header><p><label>Tibiotalar joint:<\/label><span>Normal. <\/span><\/p><p><label>Subtalar joint:<\/label><span>Normal. <\/span><\/p><p><label>Tarsal joints:<\/label><span>Normal. <\/span><\/p><\/section><section><header>ANTERIOR COMPARTMENT<\/header><p><label>Anterior tibial tendon:<\/label><span>Normal. <\/span><\/p><p><label>Extensor hallucis longus:<\/label><span>Normal. <\/span><\/p><p><label>Extensor digitorum longus:<\/label><span>Normal. <\/span><\/p><p><label>Peroneus tertius:<\/label><span>Absent. <\/span><\/p><\/section><section><header>GENERAL FINDINGS<\/header><p><label>Bones:<\/label><span>Normal. <\/span><\/p><p><label>Muscles:<\/label><span>Normal. <\/span><\/p><p><label>Tarsal tunnel:<\/label><span>Normal. <\/span><\/p><p><label>Sinus tarsi:<\/label><span>Normal. <\/span><\/p><\/section><section><header>IMPRESSION<\/header><p><span style=\"display:inline-block\">1.  <\/span><\/p><\/section><\/section><\/div><div id=\"sigblock\">\r\nElectronically signed:<br><br>Reader Profile:  1<br>Stephen Douglas Scotti M.D.<br>2020-07-05 18:39:46<\/div><div id=\"disclaimer\">PRIVILEGED AND CONFIDENTIAL: The information contained in this report and communicaition contains privileged and confidential information, including patient information protected by federal and state privacy laws. It is intended only for the use of the person(s) with authorized access. If you are not the intended recipient or are not authorized access, you are hereby notified that any review, dissemination, distribution, or duplication of this communication is strictly prohibited. If you are not an intended and authoorized recipient, please contact the sender by reply email (if received via email) or otherwise contact them and destroy all copies of the original message.<\/div><\/div>","method":"html","title":"HTML TO PDF, Sample Report","studyuuid":"e6596260-fdf91aa9-0257a3c2-4778ebda-f2d56d1b","return":1,"attach":1}'

# curl -k http://localhost:8042/pdfkit/htmltopdf -d '{"method":"base64","title":"BASE64 TO PDF","studyuuid":"e6596260-fdf91aa9-0257a3c2-4778ebda-f2d56d1b","base64":"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PDAwNjg+IDwwMDY5PiA8MDA3Mz4gPDAwMDk+IDwwMDYxPiA8MDA3ND4gPDAwNjU+IF0KZW5kYmZyYW5nZQplbmRjbWFwCkNNYXBOYW1lIGN1cnJlbnRkaWN0IC9DTWFwIGRlZmluZXJlc291cmNlIHBvcAplbmQKZW5kCgplbmRzdHJlYW0KZW5kb2JqCjYgMCBvYmoKPDwgL1R5cGUgL0ZvbnQKL1N1YnR5cGUgL1R5cGUwCi9CYXNlRm9udCAvVGltZXNOZXdSb21hblBTTVQKL0VuY29kaW5nIC9JZGVudGl0eS1ICi9EZXNjZW5kYW50Rm9udHMgWzE0IDAgUl0KL1RvVW5pY29kZSAxNSAwIFI+PgplbmRvYmoKMiAwIG9iago8PAovVHlwZSAvUGFnZXMKL0tpZHMgClsKNSAwIFIKXQovQ291bnQgMQovUHJvY1NldCBbL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUNdCj4+CmVuZG9iagp4cmVmCjAgMTcKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDA5IDAwMDAwIG4gCjAwMDAwMDQ3ODUgMDAwMDAgbiAKMDAwMDAwMDE2MyAwMDAwMCBuIAowMDAwMDAwMjU4IDAwMDAwIG4gCjAwMDAwMDAzNDQgMDAwMDAgbiAKMDAwMDAwNDY0MiAwMDAwMCBuIAowMDAwMDAwMjk1IDAwMDAwIG4gCjAwMDAwMDA2NTAgMDAwMDAgbiAKMDAwMDAwMDk0NyAwMDAwMCBuIAowMDAwMDAwNDY0IDAwMDAwIG4gCjAwMDAwMDA2MzAgMDAwMDAgbiAKMDAwMDAwMDk2NiAwMDAwMCBuIAowMDAwMDAxMjI3IDAwMDAwIG4gCjAwMDAwMDM5MTcgMDAwMDAgbiAKMDAwMDAwNDE3MCAwMDAwMCBuIAowMDAwMDAzODk2IDAwMDAwIG4gCnRyYWlsZXIKPDwKL1NpemUgMTcKL0luZm8gMSAwIFIKL1Jvb3QgNyAwIFIKPj4Kc3RhcnR4cmVmCjQ4ODMKJSVFT0YK","return":1,"attach":1}'

def attachbase64pdftostudy(query):

	attachresponse = dict()

	if query['studyuuid'] != "":
		query = '{"Tags" : {"Modality":"OT", "SeriesDescription":"' + query['title'] + '","SOPClassUID":"1.2.840.10008.5.1.4.1.1.104.1"},"Content" : "data:application/pdf;base64,' + query['base64'] + '", "Parent":"' + query['studyuuid']+ '"}'
		orthanc.RestApiPost('/tools/create-dicom',query)
		attachresponse['create-dicom-response'] = "Sent to PACS."
	else:
		attachresponse['create-dicom-response'] = "Missing UUID for parent study."
	return attachresponse;

def getpdf(query, output):

	response = dict()
	
	if query['method'] == "html":
	
		try:
			options = {
				'page-size': 'A4',
				'margin-top': '0.75in',
				'margin-right': '0.75in',
				'margin-bottom': '0.75in',
				'margin-left': '0.75in',
			}
			config = pdfkit.configuration(wkhtmltopdf=bytes("/usr/local/bin/wkhtmltopdf", 'utf-8'))
			pdf = pdfkit.from_string(query['html'], False,options=options)
			encoded = base64.b64encode(pdf).decode()
			# If attach flag is 1 then attach it to the studyuuid
			
			if query['attach'] == 1:
				query['base64'] = encoded
				response['attachresponse'] = attachbase64pdftostudy(query)
			elif query['return'] == 1:
				response['base64'] = encoded
			output.AnswerBuffer(json.dumps(response, indent = 3), 'application/json')
			
		except Exception as e:
		
			response['error'] = str(e)
			output.AnswerBuffer(json.dumps(response, indent = 3), 'application/json')
			
	elif query['method'] == "base64":
		response['attachresponse'] = attachbase64pdftostudy(query)
		output.AnswerBuffer(json.dumps(response, indent = 3), 'application/json')
	else:
		response['error'] = "Invalid Method"
		output.AnswerBuffer(json.dumps(response, indent = 3), 'application/json')

def HTMLTOPDF(output, uri, **request):

	if request['method'] != 'POST':
		output.SendMethodNotAllowed('POST')
	else:
		query = json.loads(request['body'])
		pdf = getpdf(query, output)
		
orthanc.RegisterRestCallback('/pdfkit/htmltopdf', HTMLTOPDF)