#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 by Christian Tremblay, P.Eng <christian.tremblay@servisys.com>
#
# Licensed under LGPLv3, see file LICENSE in this source tree.
"""
This module will start the Flask server 
"""
from threading import Thread
import weakref
import logging
from flask import Flask, render_template, jsonify, request
from flask_bootstrap import Bootstrap
import json
from bokeh.embed import server_document

from .templates import create_sidebar, create_card, update_notifications
from flask.logging import default_handler


class FlaskServer(Thread):

    # Init thread running server
    def __init__(self, network, port=8111, ip="0.0.0.0", *, daemon=True):
        Thread.__init__(self, daemon=daemon)
        self.flask_app = Flask(__name__)
        Bootstrap(self.flask_app)
        self._network_ref = weakref.ref(network)
        self.port = port
        self.ip = ip
        self.notifications_log = []
        self.notifications_list = ""
        self.config_flask_app()
        self.exitFlag = False

    @property
    def network(self):
        return self._network_ref()

    def run(self):
        self.process()

    def process(self):
        while not self.exitFlag:
            self.task()

    def startServer(self):
        self.flask_app.run(port=self.port, host="0.0.0.0")
        self.flask_app.logger.removeHandler(default_handler)

    def config_flask_app(self):
        @self.flask_app.route("/trends", methods=["GET"])
        def bkapp_trends_page():
            if self.network.number_of_registered_trends > 0:
                script = server_document("http://{}:5006/trends".format(self.ip))
            else:
                script = "<div>No trend registered yet...</div>"
            return render_template(
                "trends.html",
                sidebar=create_sidebar(trends_class='class="active"'),
                bokeh_script=script,
                template="Flask",
            )

        #        @self.flask_app.route('/devices', methods=['GET'])
        #        def bkapp_devices_page():
        #            script = server_document('http://localhost:5006/devices')
        #            return render_template("embed.html", script=script, template="Flask")

        @self.flask_app.route("/notes", methods=["GET"])
        def bkapp_notes_page():
            script = server_document("http://{}:5006/notes".format(self.ip))
            return render_template("embed.html", script=script, template="Flask")

        @self.flask_app.route("/", methods=["GET"])
        def home_page():
            # Stat number of devices
            cnod = create_card(
                icon="ti-server",
                title="Number of devices",
                data=self.network.number_of_devices,
                id_data="devices",
                foot_icon="ti-reload",
                foot_data="Refresh to update",
            )
            cnot = create_card(
                icon="ti-bar-chart",
                title="Number of trends",
                data=self.network.number_of_registered_trends,
                id_data="trends",
                foot_icon="ti-timer",
                foot_data="Add trends !",
            )

            cnmn = create_card(
                icon="ti-plug",
                title="{} MSTP Networks".format(
                    len(self.network.network_stats["mstp_networks"])
                ),
                data="# {}".format(self.network.network_stats["print_mstpnetworks"]),
                id_data="mstpnetworks",
                foot_icon="ti-timer",
                foot_data="Last update : {}".format(
                    self.network.network_stats["timestamp"]
                ),
                id_foot_data="lastwhoisupdate",
            )

            notif = update_notifications(self.notifications_log, None)
            return render_template(
                "dashboard.html",
                sidebar=create_sidebar(dash_class='class="active"'),
                card_number_of_devices=cnod,
                card_number_of_mstp_networks=cnmn,
                card_number_of_trends=cnot,
                notifications=notif,
                template="Flask",
            )

        @self.flask_app.route("/dash_devices", methods=["GET"])
        def dashboard_devices_page():
            script = server_document("http://{}:5006/devices".format(self.ip))
            return render_template(
                "device_table.html",
                sidebar=create_sidebar(devices_class='class="active"'),
                bokeh_script=script,
                template="Flask",
            )

        @self.flask_app.route("/_dash_live_data", methods=["GET"])
        def dash_live_data():
            devices = self.network.number_of_devices
            trends = self.network.number_of_registered_trends
            return jsonify(
                number_of_devices=devices, number_of_registered_trends=trends
            )

        @self.flask_app.route("/_whois", methods=["GET"])
        def whois():
            self.notifications_list = update_notifications(
                self.notifications_log, "Sent a WhoIs Request"
            )
            self.network.discover()
            return jsonify(done="done")

        @self.flask_app.route("/_dash_live_stats", methods=["GET"])
        def dash_live_stats():
            stats = self.network.network_stats
            return jsonify(stats=stats)

        @self.flask_app.route("/_network_pie_chart", methods=["GET"])
        def net_pie_chart():
            stats = self.network.number_of_devices_per_network()
            return jsonify(stats=stats)

        @self.flask_app.route("/log", methods=["POST", "GET"])
        def log_page():
            return json.dumps(request.form)

    def task(self):
        try:
            self.startServer()
        except Exception as err:
            self._log.warning("Flask server already running", err)
            self.exitFlag = True

    def stop(self):
        self._log.debug("Trying to stop Bokeh Server")
        # self.bokeh_server.stop()
        self.p.terminate()
        self.exitFlag = True

    def beforeStop(self):
        """
        Action done when closing thread
        """
        pass