#!/usr/bin/env python3
"""
This is a small python webserver intended to run on a testing network resource
where the lf_kinstall.pl script can post build machine information to. A useful
place to install this script would be on an APU2 being used as a VPN gateway.
Use these commands to install LaTeX and html2ps
    apt install perlmagick libwww-perl libhtml-parser-perl libpaper-utils ghostscript weblint-perl texlive-base postscript-viewer xhtml2ps html2ps
Consider these commands to install printer drivers:
Dymo LabelWriter-450:
    apt install printer-driver-dymo
Brother QL-800:
    # apt install brother-cups-wrapper-common brother-cups-wrapper-extra brother-lpr-drivers-common brother-lpr-drivers-extra
    Download drivers here:
    https://support.brother.com/g/b/downloadtop.aspx?c=us&lang=en&prod=lpql800eus
    * download driver
    * install driver using
        $ sudo dpkg -i dymo*.dpkg
Use these commands to install the script:
    $ sudo cp label-printer.py /usr/local/bin
    $ sudo chmod a+x /usr/local/bin/label-printer.py
    $ sudo cp label-printer.service /lib/systemd/system
    $ sudo systemctl add-wants multi-user.target label-printer.service
    $ sudo systemctl daemon-reload
    $ sudo systemctl restart label-printer.service
At this point, if you use `ss -ntlp` you should see this script listening on port 8082.
If you are running ufw on your label-printer host, please use this command to allow
traffice to port 8082:
$ sudo ufw allow 8082/tcp
$ sudo ufw reload
Using kinstall to print labels:
Dymo LabelWriter:
    $ ./lf_kinstall.pl --print-label http://192.168.9.1:8082/ --printer LabelWriter-450
Brother QL-800:
    $ ./lf_kinstall.pl --print-label http://192.168.9.1:8082/ --printer QL800
"""
import os
import logging
import math
from datetime import datetime
from http import server
from http.server import HTTPServer, BaseHTTPRequestHandler
from ssl import wrap_socket
from urllib.parse import urlparse, parse_qs
import pprint
from pprint import pprint
class LabelPrinterRequestHandler(BaseHTTPRequestHandler):
    def do_HEAD(self):
        self.send_response(200);
        self.send_header("Content-type", "text/html")
        self.end_headers()
    def do_GET(self):
        self.send_response(200);
        self.send_header("Content-type", "text/html")
        self.end_headers()
    def popstr(self, param):
        #print ("""TYPE : "%s" """%type(param))
        #print ("""TYPE0: "%s" """%type(param[0]))
        if type(param) is list:
            #print("""LIST: "%s", """%param[0])
            return str(param[0])
        return str(param)
    def do_POST(self):
        html_filename = "/tmp/label.html"
        printer = ""
        hostname = "";
        mac_address = "";
        model = "";
        serial = "";
        
        length = int(self.headers['Content-Length'])
        field_data = self.rfile.read(length).decode("utf-8")
        print("Field_data: %s\n"%field_data);
        fields = parse_qs(field_data)
        #pprint(fields)
        
        #for name in fields:
        #    print("""key %s: "%s" %s""" % (name, self.popstr(fields[name]), type(fields[name])))
        if "printer" in fields:
            printer = self.popstr(fields["printer"])
            if (printer is None) or ("" == printer):
                err_msg = "printer empty or unset"
                self.send_resonse(400)
                self.send_header("X-Error", err_msg)
                self.end_headers()
                self.wfile.write(b"
 %s\n"%err_msg)
                return
        else:
            err_msg = "printer not submitted"
            self.send_response(400)
            self.send_header("X-Error", err_msg)
            self.end_headers();
            self.wfile.write(b"%s\n" % err_msg);
            return
        if "mac" in fields:
            mac_address = self.popstr(fields["mac"])
            if (mac_address is None) or ("" == mac_address):
                err_msg = "mac address empty or unset"
                self.send_resonse(400)
                self.send_header("X-Error", err_msg)
                self.end_headers()
                self.wfile.write(b" %s\n"%err_msg)
                return
        else:
            err_msg = "mac address not submitted"
            self.send_response(400)
            self.send_header("X-Error", err_msg)
            self.end_headers();
            self.wfile.write(b"%s\n" % err_msg);
            return
        
        if "model" in fields:
            model = self.popstr(fields["model"])
            if (model is None) or (model == ""):
                err_msg = "model name not submitted"
                self.send_reponse(400)
                self.send_header("X-Error", err_msg)
                self.end_headers()
                self.wfile.write(b" %s\n"%err_msg)
                return
        else:
            err_msg = "model name not submitted"
            self.send_response(400)
            self.send_header("X-Error", err_msg)
            self.wfile.write(b"%s\n" % err_msg);
            return
        if "hostname" in fields:
            hostname = self.popstr(fields["hostname"])
        else:
            suffix = mac_address[-5:].replace(":", "")
            hostname = "%s-%s"%(model, suffix)
        if "serial" in fields:
            serial = self.popstr(fields["serial"])
        else:
            serial = hostname
        now = datetime.now()
        datestr = now.strftime("%Y-%m")
        self.send_response(200);
        self.send_header("Content-type", "text/html")
        self.end_headers()
        label_html = self.html_template(model_=model, mac_=mac_address, hostname_=hostname, serial_=serial, datestr_=datestr)
        if os.path.exists(html_filename):
            try:
                os.remove(html_filename)
            except:
                err_msg = "unable to remove html file"
                self.send_response(400)
                self.send_header("X-Error", err_msg)
                self.wfile.write(b"%s\n" % err_msg);
                return
        try:
            file = open(html_filename, "w")
            file.write(label_html)
            file.close()
        except:
            err_msg = "unable to write html file"
            self.send_response(400)
            self.send_header("X-Error", err_msg)
            self.wfile.write(b"%s\n" % err_msg);
            return
        self.print_pdf(printer=printer, html=html_filename)
        self.wfile.write(b"Success\n")
    def html_template(self, model_="unset", mac_="unset", hostname_="unset", serial_="unset", datestr_="unset"):
        template = """
  
   | Model: | %s (%s) | 
  
   | MAC: | %s | 
   | Hostname: | %s | 
   | Serial: | #%s | 
""" % (model_, datestr_, mac_, hostname_, serial_)
        return template
    def print_pdf(self, printer, html ):
        """
        :param printer:
        :param html:
        :return:
        """
        """ Below is shell script that worked:
w_inches="3.45"
h_inches="1.125"
w_points=`echo "scale=0; ($w_inches * 72)/1" | bc -l`
w_px=`echo "scale=0; ($w_inches * 720)/1" | bc -l`
h_points=`echo "scale=0; ($h_inches * 72)/1" | bc -l`
h_px=`echo "scale=0; ($h_inches * 720)/1" | bc -l`
echo "Page size in Points: $w_points x $h_points"
echo "Page size in pixels: $w_px x $h_px"
rm -f label.pdf
set -x
html2ps -L label.html \
| gs -o label.pdf \
   -g${h_px}x${w_px} \
   -sDEVICE=pdfwrite \
   -dFIXEDMEDIA \
   -dPDFFitPage \
   -dFitPage \
   -c '<> setpagedevice' \
   -f -
"""
        w_inches = 3.45
        h_inches = 1.125
        w_points = math.floor(w_inches * 72)
        w_px = math.floor(w_inches * 720)
        h_points = math.floor(h_inches * 72)
        h_px = math.floor(h_inches * 720)
        pdf_file = "/tmp/label.pdf"
        pageoffset = "<> setpagedevice"
        geometry = "-g{}x{}".format(h_px, w_px)
        if os.path.exists(pdf_file):
            try:
                os.remove(pdf_file)
            except:
                err_msg = "unable to remove html file"
                self.send_response(400)
                self.send_header("X-Error", err_msg)
                self.wfile.write(b"%s\n" % err_msg);
                return
        cmd = """html2ps -L "%s" | gs -o "%s" %s -sDEVICE=pdfwrite -dFIXEDMEDIA -dPDFFitPage -dFitPage -c '%s' -f -""" \
              % (html, pdf_file, geometry, pageoffset)
        print("CMD: "+cmd)
        try:
            os.system(cmd)
            os.system("""lp -d "%s" -- "%s" """%(printer, pdf_file))
        except:
            err_msg = "trouble printing pdf"
            self.send_response(500)
            self.send_header("X-Error", err_msg)
            self.wfile.write(b"%s\n" % err_msg);
            return
def __main__():
    logging.info("Main Method. Creating CGI Handler")   
    httpd = HTTPServer(('', 8082), LabelPrinterRequestHandler)
    print("Starting LabelPrinter service...")
    httpd.serve_forever()
if __name__ == "__main__":
    __main__()