"""
Name: wifi_controller
Title:
Author: Cooper
Date: 12/09/2023

Desc:  This is for allowing one to drive signs over the network via a web interface.

This was originally written by Claudio Gil which has since seen many iterations before ending up as this.
The key difference in this is that a lot of the dependencies needed are no longer required.  Everything is done via
Bottle.

"""
import time
import _thread
import threading

from urllib.parse import unquote
from bottle import route, run, template, request, Bottle, HTTPResponse

from hanip.onionip.console import console_task
from hanip.onionip.console import sign_manager
from hanip.onionip.sign import template_generator
from hanip.onionip.sign import sign_task


class WebApp(object):
    def __init__(self, config_dict, hw_dict, conf_dir, data_dir):
        self.config_dict = config_dict
        self.hw_dict = hw_dict
        self.config_dir = conf_dir
        self.data_dir = data_dir

        self.new_data = False
        self.data_dict = None
        self.flippy_data = None

    def setup_webserver(self):
        self.http_server = Bottle()
        self.http_port = 8080

        self.http_server.route('/', method="GET", callback=self.root_page)
        self.http_server.route('/', method="POST", callback=self.process_post)
        self.http_server.route('/sms', method="POST", callback=self.handle_sms)
        self.http_server.route('/flippyhcp', method="POST", callback=self.handle_flippy_hcp)

        self.http_thread = threading.Thread(target=self.http_server.run, kwargs=dict(host="0.0.0.0",
                                                                                     port=self.http_port,
                                                                                     debug=False
                                                                                     ))

        self.http_thread.daemon = True
        self.http_thread.start()

    def handle_flippy_hcp(self):
        """
        Handles Data from Raymond's Flippy application
        """
        self.new_data = True
        self.data_dict = None

        flippy_data = request.body.read().decode("utf-8")
        print(flippy_data)

        self.flippy_data = flippy_data

        return HTTPResponse(status=200)
    def update_display_dict(self, rn, topline, bottomline):
        """
        Updates the dictionary so that whatever wants to consume it has a standard format.
        """
        self.new_data = True
        self.flippy_data = None

        if bottomline != "":
            dest = "%s/%s" % (topline, bottomline)
        else:
            dest = topline

        self.data_dict = {
            "$bcol": "0,0,0",
            "$fcol": "255,255,255",
            "$rn": rn,
            "$dest": [dest]
        }

        print(self.data_dict)

    def get_webform(self):
        """
        This is the text entry box in very rusty HTML and CSS
        """
        form_html = '''
        <!DOCTYPE html>
        <html>
        <head>
        <style>
        h1 {
            margin: 0 auto;
            color: black;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 200%;
        }
        h2 {
            margin: 0 auto;
            color: black;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 100%;
        }
        form {
            height: auto; /*if more info comes on the page, it will stretch down*/
            width: 300px;
            font-size: 30px;
            height: 4em;
            font-family: Arial, Helvetica, sans-serif;
        }
        .form{
            font-size: 22px;
        }
        .button{
            font-size: 22px;
            font-family: Arial, Helvetica, sans-serif;
        }
        </style>
        </head>
        <body>

        <h1>Hanover Displays</h1>
        <h2>Web sign controller</h2>
        <form method="POST" action="/" enctype="multipart/form-data">
        <input type="text" name="rn" placeholder="Route Number">
        <input type="text" name="topline" placeholder="Top Line">
        <input type="text" name="bottomline" placeholder="Bottom Line">
        <br>
        <input type="submit" name="submit"  value="Submit" >
        </form>
        </body>
        </html>
        '''

        return form_html

    def root_page(self):
        """
        Just serves up the webpage
        """
        return self.get_webform()

    def process_post(self):
        """
        Takes the data that was POSTed and sets the flags
        """
        self.update_display_dict(
            request.forms["rn"],
            request.forms["topline"],
            request.forms["bottomline"]
        )

        return self.get_webform()

    def handle_sms(self):
        """
        For when Teltonika SMS are POSTed
        """
        raw_sms = request.body.read().decode("utf-8")
        splititems = raw_sms.split("&")

        for item in splititems:
            if item.startswith("message="):
                raw_message = item[8:]

                # We then need to unquote it:
                message = unquote(raw_message)
                self.parse_sms(message)
                break

        return HTTPResponse(status=200)

    def parse_sms(self, message):
        """
        Parses the message based on the HILDE format
        """
        # Get RN if appropriate:
        split_items = message.split("%")

        if len(split_items) > 1:
            rn = split_items[0]
            dest = split_items[1].replace("<", "/")
        else:
            rn = ""
            dest = message.replace("<", "/")

        self.update_display_dict(rn, dest, "")


class WebAppConsole(WebApp):
    def __init__(self, config_dict, hw_dict, config_dir, data_dir):
        super().__init__(config_dict, hw_dict, config_dir, data_dir)
        self.display_text = ""

    def update_sign_manager(self):
        """
        Generates the dictionary for sign manager and updates it.
        """
        rn = self.data_dict["$rn"]
        dest = self.data_dict["$dest"][0]

        self.display_text = "%s %s" % (rn, dest.replace("/", " "))
        self.console_task.remote_message = (self.display_text, 0, 0)

        filled_templates_mono, filled_templates_col = self.tg.generate_templates(self.data_dict)
        sign_data = filled_templates_mono[2]

        self.sign_manager.update_data_from_console_task([sign_data] * 14)

    def setup(self):
        """
        Sets up all the background tasks needed to run on the console
        """
        self.tg = template_generator.TemplateGenerator(self.config_dict, self.data_dir)

        #Console task is overkill but we need to keep it for USB updating
        self.console_task = console_task.ConsoleTask(self.config_dict, self.hw_dict, self.config_dir, self.data_dir)
        _thread.start_new_thread(self.console_task.run_sign_data_mode, ())

        self.sign_manager = sign_manager.SignManagerConsole(self.config_dict, self.data_dir)
        _thread.start_new_thread(self.sign_manager.run, ())


    def run(self):
        """
        Main look for running on a console
        """
        self.setup()
        self.setup_webserver()
        self.console_task.remote_message = ("Waiting for message", 0, 0)

        while 1:
            if self.new_data:
                self.new_data = False
                self.update_sign_manager()

            if self.console_task.stop:
                break

            time.sleep(1)


class WebAppSign(WebApp):
    def __init__(self, config_dict, hw_dict, config_dir, data_dir):
        super().__init__(config_dict, hw_dict, config_dir, data_dir)

    def update_sign_task(self):
        """
        Generates the dictionary for sign manager and updates it.
        """
        if self.data_dict is not None:
            self.sign_task.update_data_dict(self.data_dict)
        elif self.flippy_data is not None:
            self.sign_task.update_data(self.flippy_data, render=False)

    def setup(self):
        """
        Sets up sign task in a thread
        """
        self.sign_task = sign_task.SignTask(self.config_dict, self.hw_dict, self.config_dir, self.data_dir)
        _thread.start_new_thread(self.sign_task.run, ())

    def run(self):
        """
        Main loop for the signs
        """
        self.setup()
        self.setup_webserver()

        while 1:
            if self.new_data:
                self.new_data = False
                self.update_sign_task()

            time.sleep(1)


if __name__ == "__main__":
    wa = WebApp(None, None, None, None)
    wa.setup_webserver()

    while 1:
        time.sleep(10)
