import matplotlib
# Allow running headless from the command line
matplotlib.use("agg")

import sys
import os
import glob
import time
import datetime
import signal
import math
import threading
import json
import RXTools
import argparse
import logging
from logging.handlers import RotatingFileHandler
from numpy import *
from pylab import *
from flask import Flask, render_template, render_template_string, Markup, Response, request, jsonify, send_from_directory
from flask_compress import Compress
try:
    from urllib.request import urlopen
except ImportError:
    from urllib2 import urlopen

# Port at which the service will run - don't run a 
# second instance of this without changing this!!
webPort = 81
# We use this frame work to get SV tracking data
# from mulitple stations and provide as an 
# XML output. If you won't want this feature set
# to False
runGetSVData = True
enableServerLogs = True

# Use the current time to initialize a few variables
secondsSysRequest = datetime.datetime.now()
secondsSvRequest = datetime.datetime.now()
ThreadsActive = True

app = Flask(__name__)
Compress(app)

# This intercepts the web requests, it allows us to filter and
# provides a central place for logging
@app.before_request
def limit_remote_addr():
  if(request.remote_addr == '10.1.187.20'):
    # Block Trimble's scanner which messes up the logs
    return "", 403
  else:
    if(request.remote_addr != '10.1.148.238'):
      # Don't log the requests for svData.xml from daffy's mashup
      if(enableServerLogs == True):
        app.logger.info("%s %s" % (request.remote_addr, request.url))

# If we get a 404 (page not found) log an error
@app.errorhandler(404)
def handle404(error):
  if(enableServerLogs == True):
    app.logger.error("%s %s" % (request.remote_addr, request.url))
  return "", 404

@app.route("/")
def main():
  return index()


@app.route('/favicon.ico')
def favicon():
  return send_from_directory(os.path.join(app.root_path, 'static'),
                             'favicon.ico', mimetype='image/vnd.microsoft.icon')

@app.route("/RXReset.html")
def RXReset():
    return "Place Holder - RXReset!"

@app.route("/stations.json")
def stations():
  jsonData = jsonify(stations)
  #jsonStr = json.dumps(stations)
  #return render_template_string(Markup(jsonStr))
  return jsonData



@app.route("/index.html")
def index():
  webStr = ("{% extends 'menu.html' %}")
  webStr = webStr + ("{% block main %}")

  webStr = webStr + ("<section id='content'>")
  webStr = webStr + ("<div class='col'>")
  webStr = webStr + "<div class='col-sm-12'>"

  webStr += ("<p>GNSS Receiver Monitoring</p>")
  webStr += ("<span id='SystemStatus'></span>")
  webStr += ("<br/>")
  webStr += ("<div id='tabSpan'></div>")
  webStr += ("<div id='trackingSpan'></div>")
  webStr += ("<br/>")

  webStr = webStr + ("</div></div>")

  webStr = webStr + ("</section>")

  webStr = webStr + ("{% endblock %}")
  webStr = webStr + ("{% block userscript %}")

  webStr = webStr + ("<script src='static/js/app.js'></script>")
  webStr += "<link href='static/trimbleRX.css' rel='stylesheet'>"
  webStr += "<script language='Javascript' src='static/jquery.js'></script>"
  #webStr += "<script language='JavaScript' src='static/stations.js'></script>"
  #webStr += "<script language='JavaScript' src='stations.json'></script>"
  webStr += "<script language='JavaScript' src='static/monitorNew.js'></script>"
  webStr += "<script language='JavaScript' src='static/coreAjax.js'></script>"


  webStr = webStr + ("<script>init();</script>")
  
  
  
  webStr = webStr + ("{% endblock %}")
  return render_template_string(Markup(webStr))


def signal_handler(signal, frame):
  global ThreadsActive
  print('You pressed Ctrl+C!')
  ThreadsActive = False

  if(runGetSVData == True):
    time.sleep(5)
    for i in range(len(threadsSVdata)):
      threadsSVdata[i].join()
    for i in range(len(threadsSYSdata)):
      threadsSYSdata[i].join()
  
  print("Exiting")
  sys.exit(0)


def worker(num):
  while(ThreadsActive == True):
    resp = []
    global secondsSvRequest

    delta = (datetime.datetime.now() - secondsSvRequest).total_seconds()
    #print("%d SV-delta = %f" % (num,delta))
    if( delta < 60 ):
      try:
        resp = RXTools.SendHttpPost( stations[num].get("addr"),
                             '/xml/dynamic/svData.xml',
                             stations[num].get("user"),
                             stations[num].get("pw"))
      except:
        pass
        #print("Exception(SV) Task %d:%s" % (num, stations[num].get("long")))

      if(resp):
        xmlSVData[num] = resp
        #print('Worker-SV[%d]: %s got response Active = %d' % (num,stations[num].get("long"),ThreadsActive))

    time.sleep(3)
  return

def workerSys(num):
  while(ThreadsActive == True):
    resp = []
    global secondsSysRequest

    delta = (datetime.datetime.now() - secondsSysRequest).total_seconds()
    #print "%d SYS-delta = %f" % (num,delta)
    if( delta < 240 ):
      try:
        resp = RXTools.SendHttpPost( stations[num].get("addr"),
                             '/xml/dynamic/sec_merge.xml?sysData=&powerData=&posData=&power=&pos=&options=',
                             stations[num].get("user"),
                             stations[num].get("pw"))
      except:
        try:
          resp = RXTools.SendHttpPost( stations[num].get("addr"),
                               '/xml/dynamic/merge.xml?sysData=&powerData=&posData=&power=&pos=&options=',
                               stations[num].get("user"),
                               stations[num].get("pw"))
        except:
          print("Exception Task(SYS) %d:%s" % (num, stations[num].get("long")))

      if(resp):
        xmlSYSData[num] = resp
        #print 'Worker-SYS[%d]: %s got response Active = %d' % (num,stations[num].get("long"),ThreadsActive)

    time.sleep(10)
  return

@app.route("/svData.xml")
def svData():
  global secondsSvRequest
  webStr = "<data>"

  for i in range(len(xmlSVData)):
    if(len(xmlSVData[i]) > 0):
      webStr = webStr + "<station><name>" + stations[i].get("long") + "</name>"
      #webStr = webStr + xmlSVData[i] + "</station>"
      webStr = webStr + "<data>" + xmlSVData[i] + "</data></station>"
  webStr = webStr + "</data>"
  
  # Get the time of the request
  secondsSvRequest = datetime.datetime.now()  

  return Response(webStr,mimetype='text/xml')


@app.route("/sysData.xml")
def sysData():
  global secondsSysRequest
  webStr = "<data>"

  for i in range(len(xmlSYSData)):
    if(len(xmlSYSData[i]) > 0):
      webStr = webStr + "<station><name>" + stations[i].get("long") + "</name>"
      webStr = webStr + xmlSYSData[i] + "</station>"
  webStr = webStr + "</data>"
  
  # Get the time of the request
  secondsSysRequest = datetime.datetime.now()  

  return Response(webStr,mimetype='text/xml')

os.environ['http_proxy'] = 'proxy.trimble.com:3128'
if __name__ == "__main__":


  ######################################################################
  # Parse arguments
  parser = argparse.ArgumentParser(description='Web Application providing receiver status')
  parser.add_argument('-s','--stations', help='Filename of the station JSON e.g. --stations global.json')
  parser.add_argument('-p','--port', help='Optional HTTP port, by default 81 e.g. --port 80')
  args = parser.parse_args()
  ######################################################################


  # Load the list of stations
  if(args.stations):
    with open(args.stations,'r') as f: 
      stations = json.load(f)
  else:
    print('require a station JSON file')
    sys.exit(1)

  if(args.port):
    webPort = int(args.port)

  signal.signal(signal.SIGINT, signal_handler)
  print("Setup CTRL-C handler")
  if(runGetSVData == True):
    threadsSVdata = []
    threadsSYSdata = []
    xmlSVData = []
    xmlSYSData = []
    # Kick off the threads
    for i in range(len(stations)):
      xmlSVData.append('')
      xmlSYSData.append('')
      t = threading.Thread(target=worker, args=(i,))
      threadsSVdata.append(t)
      t.start()
      t = threading.Thread(target=workerSys, args=(i,))
      threadsSYSdata.append(t)
      t.start()

  if(enableServerLogs == True):
    formatter = logging.Formatter(
          "[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s")
    handler = RotatingFileHandler('webApp.log', maxBytes=(1024*128), backupCount=64)
    handler.setLevel(logging.DEBUG)
    handler.setFormatter(formatter)
    app.logger.addHandler(handler)
    app.logger.setLevel(logging.DEBUG)
  
  try:
    app.run(host='0.0.0.0',port=webPort,threaded=True)
  except:
    sys.exit(1)


