#!/usr/bin/python

import os, glob, re, time
from flask import Flask, request, redirect, url_for, make_response, render_template
from flask import send_from_directory, g
from werkzeug import secure_filename
from werkzeug.routing import BaseConverter

app = Flask(__name__)
app.debug = True
app.version = 1.1

base = os.path.dirname(os.path.realpath(__file__))

class RegexConverter(BaseConverter):
  def __init__(self, url_map, *items):
    super(RegexConverter, self).__init__(url_map)
    self.regex = items[0]

app.url_map.converters['regex'] = RegexConverter

@app.before_request
def before_request():
  g.start = time.time()

@app.after_request
def add_header(response):
  diff = time.time() - g.start
  response.headers['Cache-Control'] = "max-age=0, no-cache, no-store, must-revalidate"
  response.headers['Expires'] = "Thu, 29 Nov 1984 19:40:00"
  response.headers['Pragma'] = "no-cache"
  response.headers['Run-in'] = os.path.dirname(os.path.abspath(__file__))
  response.headers['CWD'] = os.path.dirname(os.getcwd())
  response.headers['X-LOST'] = '4 8 15 16 23 42'
  response.headers['X-Runtime'] = "%1.1f ms" % (diff*1000)
  response.headers['X-App-Version'] = app.version
  return response

@app.route("/<regex('(img|css|js)'):head>/<resource>")
def get_static(head, resource):
  return redirect(url_for('static', filename=head + '/' + resource))

@app.route("/<regex('(font|fonts)'):head>/<resource>")
def get_images(head, resource):
  return redirect(url_for('static', filename='fonts/'+resource))

@app.route("/pubkey/")
def get_public_key():
  return send_from_directory(os.path.join(base, 'static'), filename='pubkey/key.pub')

@app.route("/<regex('([A-Z0-9]{4,11})'):hash>/")
@app.route("/<regex('([A-Z0-9]{4,11})'):hash>/<regex('overview|accessories|dates|report|statistics|notes|feedback|acknowledgment|cleaning|quality-control'):target>")
def root(hash, target=None):
  import uuid
  my_uuid = str(uuid.uuid4()).upper()
  resp = make_response(render_template('root.html', uuid=my_uuid))
  resp.set_cookie('request', my_uuid)

  return resp

@app.route("/file/<uuid:uuid>", methods=['GET'])
def get_file(uuid):
  print uuid
  return send_from_directory('/tmp/', filename='image.jpeg')

@app.route("/intervention/<regex('([A-Z0-9]{4,11})'):hash>/<int:version>/", methods=['POST'])
def post_intervention(hash, version=0):
  import json

  payload = json.loads(request.data)
  number = payload["number"]

  import time
  time.sleep(1)

  subdir = ['interventions'] + ["%s_%s" % (number, hash)] # + time.strftime("%Y,%m").split(',') + [number]
  directory = os.path.join(base, *subdir)
  if not os.path.exists(directory):
    os.makedirs(directory)

  filename = "%s_%s_%04d.json" % (number, hash, version)
  file = open(os.path.join(directory, filename), "wb")
  file.write(request.data)
  file.close()

  import subprocess, shlex
#  shell = """%s -i -o -w %s""" % (os.path.join(base, 'xslt/json2sql.sh'), hash)
#  subprocess.Popen((shlex.split(shell)))

  return "Ahoy, capt'n"

@app.route("/intervention/<regex('([A-Z0-9]{4,11})'):hash>/<int:mode>/<int:clear>/<path:sections>", methods=['GET'])
@app.route("/intervention/<regex('([A-Z0-9]{4,11})'):hash>/<int:mode>/<int:clear>/", methods=['GET'])
def json_intervention(hash, mode, clear=0, sections=None):
  from subprocess import call, check_output
  from shlex import split
  from flask import abort, make_response
  from os import listdir, path, system

  cached = sections is None

  if cached:
    subdir = ["interventions"]
    for folder in [f for f in listdir(path.join(base, *subdir)) if re.search(hash, f)]:
      for file in [f for f in sorted(listdir(path.join(base, *(subdir + [folder]))), reverse=True)[:1]]:
        return send_from_directory(path.join(base, *(subdir + [folder])), filename=file)

  xslt1 = path.join(base, 'xslt/', 'sanitize.xslt')
  xslt2 = path.join(base, 'xslt/', 'intv_xml2json.xslt')
  sections = "'%s'" % ','.join(sections.split('/')) if sections is not None else None
  shell = """mysql -u F5VksfQsYW -h 192.168.10.10 -pmWaq9FiGC6\
  --default-character-set=utf8\
  --skip-column-names\
  --raw\
  --execute="call npro_export_xml_intervention('GER', %s, '%s', %s)"\
  NESA > /tmp/intv_%s.xml
  """ % ('NULL' if sections is None else sections, hash, 'TRUE' if clear==0 else 'FALSE', hash)
  print cached
  system(shell)

  shell = "xsltproc %s /tmp/intv_%s.xml > /tmp/intv_%s_sanitized.xml" % (xslt1, hash, hash)
  system(shell)

  if mode==1:
    shell = "xsltproc %s /tmp/intv_%s_sanitized.xml > /tmp/intv_%s.json" % (xslt2, hash, hash)
    system(shell)

    import json
    with open(("/tmp/" + "intv_%s.json") % hash) as json_data:
      intvs = json.load(json_data)
      if len(intvs)==0:
        abort(404)
      response = make_response(json.dumps(intvs[0], ensure_ascii=False).encode('utf8'))
      response.headers['Content-Type'] = 'application/json'
      return response

  import xml.dom.minidom as minidom
  interventions = minidom.parse(("/tmp/" + "intv_%s_sanitized.xml") % hash).getElementsByTagName("intervention")
  if len(interventions)==0:
    abort(404)
  xml = ['<?xml version="1.0" encoding="utf-8"?>', interventions[0].toxml()]
  response = make_response("\n".join(xml))
  response.headers['Content-Type'] = 'application/xml'
  return response

@app.route("/calendars/<regex('[0-9]{4}-[0-9]{2}-[0-9]{2}'):from_date>/<regex('[0-9]{4}-[0-9]{2}-[0-9]{2}'):until_date>/<int:active>/<int:mode>/", methods=['GET'])
@app.route("/calendars/<regex('[0-9]{4}-[0-9]{2}-[0-9]{2}'):from_date>/<regex('[0-9]{4}-[0-9]{2}-[0-9]{2}'):until_date>/<int:active>/<int:mode>/<path:varargs>/", methods=['GET'])
def calendars(from_date, until_date, mode, active, varargs=0):
  from subprocess import call, check_output
  from shlex import split
  from flask import abort, make_response
  from os import listdir, path, system

  if until_date < from_date:
    abort(400)

  xslt1 = path.join(base, 'xslt/', 'sanitize.xslt')
  xslt2 = path.join(base, 'xslt/', 'intv_xml2json.xslt')

  shell = """mysql -u F5VksfQsYW -h 192.168.10.10 -pmWaq9FiGC6\
  --default-character-set=utf8\
  --skip-column-names\
  --raw\
  --execute="call npro_export_xml_calendars('GER', '%s', '%s', %d, '%s', 1)"\
  NESA > /tmp/calendars.xml
  """ % (from_date, until_date, 1 if active==1 else 0, ",".join(str(varargs).split("/")))
  system(shell)

  shell = "xsltproc %s /tmp/calendars.xml > /tmp/calendars_sanitized.xml" % (xslt1)
  system(shell)

  if mode==1:
    shell = "xsltproc %s /tmp/calendars_sanitized.xml > /tmp/calendars.json" % (xslt2)
    system(shell)

    return send_from_directory('/tmp', filename=("calendars.json"))

  return send_from_directory('/tmp', filename=("calendars_sanitized.xml"))

@app.route("/intervention/<regex('([A-Z0-9]{4,11})'):hash>/pdf/original", methods=['GET'])
def pdf_original(hash):
  from subprocess import call, check_output
  from shlex import split
  from flask import make_response
  from os import listdir, path, system

  shell = """mysql -u F5VksfQsYW -h 192.168.10.10 -pmWaq9FiGC6\
  --default-character-set=utf8\
  --skip-column-names\
  --raw\
  --execute="select npro_notify('%s', FALSE)"\
  NESA
  """ % (hash)
#  NESA > /tmp/intv_original_%s.pdf
#  system(shell)

  pdf = check_output(split(shell))
  response = make_response(pdf)
  response.headers['Content-Type'] = 'application/pdf'
  response.headers['Content-Disposition'] = 'inline; filename=%s.pdf' % hash
  return response

@app.route("/intervention/<regex('([A-Z0-9]{4,11})'):hash>/pdf/", methods=['GET'])
def pdf_intervention(hash):
  from subprocess import call, check_output
  from shlex import split
  from flask import make_response
  from os import listdir, path, system

  xslt1 = path.join(base, 'xslt/', 'intv_report.xslt')
  xslt2 = path.join(base, 'xslt/', 'intv_xml2json.xslt')

  shell = """mysql -u F5VksfQsYW -h 192.168.10.10 -pmWaq9FiGC6\
  --default-character-set=utf8\
  --skip-column-names\
  --raw\
  --execute="call npro_export_xml_intervention('GER', NULL, '%s', %s)"\
  NESA > /tmp/intv_%s.xml
  """ % (hash, 'TRUE', hash)
  system(shell)

  shell = "xsltproc %s /tmp/intv_%s.xml > /tmp/intv_%s_report.html" % (xslt1, hash, hash)
  system(shell)

  shell = '/usr/local/bin/./wkhtmltopdf.sh -q --title NESA -L 0 -R 0 -T 0 -B 0 --print-media-type -s A4 /tmp/intv_%s_report.html -' % hash
  #shell = 'wkhtmltopdf -q --title NESA -L 0 -R 0 -T 0 -B 0 --print-media-type -s A4 /tmp/intv_%s_report.html -' % hash
  print shell

  pdf = check_output(split(shell))
  response = make_response(pdf)
  response.headers['Content-Type'] = 'application/pdf'
  response.headers['Content-Disposition'] = 'inline; filename=%s.pdf' % hash
  return response

@app.route("/database/")
@app.route("/database/<int:mode>/")
@app.route("/database/<int:mode>/<path:varargs>/")
def database(mode=1, varargs=0):
  from subprocess import call, check_output
  from shlex import split
  from flask import abort, make_response
  from os import path, system
  
  return redirect(url_for('static', filename='database/data.json'))

#  return abort(401)

  xslt1 = path.join(base, 'xslt/', 'sanitize.xslt')
  xslt2 = path.join(base, 'xslt/', 'database.xslt')

  shell = """mysql -u F5VksfQsYW -h 192.168.10.10 -pmWaq9FiGC6\
  --default-character-set=utf8\
  --skip-column-names\
  --raw\
  --execute="call npro_export_xml_database('GER', '%s')"\
  NESA > /tmp/database.xml
  """ % ",".join(str(varargs).split("/"))
  system(shell)

  shell = "xsltproc %s /tmp/database.xml > /tmp/database_sanitized.xml" % xslt1
  system(shell)

  if mode==0:
    return send_from_directory('/tmp', filename="database_sanitized.xml")

  shell = "xsltproc %s /tmp/database_sanitized.xml > /tmp/database.json" % xslt2
  system(shell)

  return send_from_directory('/tmp', filename="database.json")

###
# Proxy wrapper class to allow Flask to run behind a reverse
# proxy (such as Apache)
#
class ReverseProxied(object):
  def __init__(self, app):
    self.app = app

  def __call__(self, environ, start_response):
    script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
    if script_name:
      environ['SCRIPT_NAME'] = script_name
      path_info = environ['PATH_INFO']
      if path_info.startswith(script_name):
        environ['PATH_INFO'] = path_info[len(script_name):]

    scheme = environ.get('HTTP_X_SCHEME', '')
    if scheme:
      environ['wsgi.url_scheme'] = scheme
    return self.app(environ, start_response)

app.wsgi_app = ReverseProxied(app.wsgi_app)

if __name__ == "__main__":
  app.run(host='0.0.0.0', port=7000, debug=True, threaded=True)
