#!/usr/bin/env python3
#
# Routino data visualiser CGI
#
# Part of the Routino routing software.
#
# This file Copyright 2008-2014, 2016, 2025 Andrew M. Bishop
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import subprocess
import os
import sys


# Change directory to the CGI location and add it at the beginning of the module search path.

cgidir = os.path.dirname(__file__)

if sys.path[0] != cgidir:
    sys.path.insert(0,cgidir)

# Use the directory paths
import paths                    # pylint: disable=wrong-import-position

# Load CGI functions
import cgifunctions             # pylint: disable=wrong-import-position


#
# The WSCGI handling function
#

def application(environ, start_response):

    # Legal CGI parameters with regexp validity check

    legalparams = {
        "latmin":      "[-0-9.]+",
        "latmax":      "[-0-9.]+",
        "lonmin":      "[-0-9.]+",
        "lonmax":      "[-0-9.]+",
        "data":        "fixmes",
        "dump":        "fixme[0-9]+",
        "statistics":  "yes"
    }

    # Validate the CGI parameters, ignore invalid ones

    rawparams = cgifunctions.parse_qs(environ['QUERY_STRING'])

    cgiparams = cgifunctions.validate_qs(rawparams, legalparams, regexp=False, fill=True)

    # File dumper parameters

    exeparams = [os.path.join(cgidir,paths.bin_dir,paths.fixme_dumper_exe)]

    if paths.data_dir != "":
        exeparams += [f"--dir={os.path.join(cgidir,paths.data_dir)}"]

    # Data, dump or statistics?

    data = cgiparams['data']
    dump = cgiparams['dump']
    stats= cgiparams['statistics']

    if ( data == "" and dump == "" and stats == "" ) or \
       ( data  != "" and dump  != "" ) or \
       ( dump  != "" and stats != "" ) or \
       ( stats != "" and data  != "" ):
        start_response("500 Invalid CGI parameters",[('Content-type', 'text/plain')])
        return [b"Must specify one of 'data' or 'dump' or 'statistics'."]

    if stats != "":

        # Set the parameters

        exeparams += ["--statistics"]

    elif data != "":

        # Parameters to limit range selected

        limits = 0.5

        # Check the parameters

        latmin = cgiparams["latmin"]
        latmax = cgiparams["latmax"]
        lonmin = cgiparams["lonmin"]
        lonmax = cgiparams["lonmax"]

        if latmin == "" or latmax == "" or lonmin == "" or lonmax == "":
            start_response("500 Invalid CGI parameters",[('Content-type', 'text/plain')])
            return [b"Must specify 'lonmin', 'latmin', 'lonmax' and 'latmax' with 'data'."]

        latmin = float(latmin)
        latmax = float(latmax)
        lonmin = float(lonmin)
        lonmax = float(lonmax)

        if (latmax-latmin)>limits or (lonmax-lonmin)>limits:
            start_response("500 Invalid CGI parameters",[('Content-type', 'text/plain')])
            return [b"Specified area is too large."]

        # Set the parameters

        exeparams += ["--visualiser", f"--data={data}"]
        exeparams += [f"--latmin={latmin}", f"--latmax={latmax}", f"--lonmin={lonmin}", f"--lonmax={lonmax}"]

    else:

        exeparams += ["--dump-visualiser", f"--data={dump}"]

    # Run the file dumper

    try:
        EXECUTE = subprocess.Popen(exeparams, stdout=subprocess.PIPE)
    except OSError:
        start_response("500 Error running process",[('Content-type', 'text/plain')])
        return [b"Error executing process to complete this request."]

    # WSGI application return values

    start_response("200 OK", [('Content-type', 'text/plain; charset=utf-8')])

    return cgifunctions.procstream(EXECUTE)


#
# From command line for debugging
#

if __name__ == '__main__':

    environ = {
        'REQUEST_SCHEME': "http",
        'HTTP_HOST': "routino.org",
        "REQUEST_URI": "/test/fixme.cgi",
        'QUERY_STRING': ";".join(sys.argv[1:])
    }

    for x in application(environ,lambda c,lh: print("\n".join([c]+[f"{h[0]}: {h[1]}" for h in lh]+[""]))):
        print(x.decode(encoding='utf-8'),end="")
