#!/usr/bin/env python
# -*- coding: utf-8 -*-

# System modules
import json
from .camera import Status as cam_status
from .dome import Status as dom_status
from .telescope import Status as tel_status
from flask import Response, render_template, make_response, request
from flask_restx import Namespace, Resource, fields
from astropy.time import Time
from time import sleep

import ping3
import socket
import requests

# Custom modules
import devices

############################
# REST API
############################

api = Namespace('home', description='Home page API')


@api.route("/ping")
class Ping(Resource):
    """Ping the servers"""

    def get(self):
        """Servers status"""

        def ping(address, timeout=0.1):
            try:
                res = ping3.ping(address, timeout=timeout)
                return True if res else False
            except Excepion as e:
                res = None

        res = {
            "response": {
                "Ascom server":      ping("ascom"),
                "Scientific camera": ping("ccd-sbig"),
                "Meteo station":     ping("meteo"),
                "TCS server":        ping("grigioni"),
                "All sky camera":    ping("130.251.11.11"),
                "Domotics server":   ping("grafana10.com.diten.unige.it"),
                "Cabinet switch":    ping("fork"),
                "Webcam":            ping("ipcam"),
            },
            "error": []
        }

        return res


@api.route("/ports")
class Ports(Resource):
    """Check the ports"""

    def get(self):
        """Port status"""

        timeout = 0.1

        def nmap(address, port):
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            try:
                connection = socket.create_connection(
                    (address, port), timeout=timeout)
                res = True
            except TimeoutError as e:
                res = None
            except ConnectionRefusedError as e:
                res = False
            except socket.gaierror:
                res = False

            sock.close()
            return res

        res = {
            "response": {
                "Ascom server":      nmap('ascom', 533),
                "Scientific camera": nmap('ccd-sbig', 80),
                "Meteo station":     nmap('meteo', 5001),
                "TCS server":        nmap('grigioni', 65432),
                "All sky camera":    nmap('130.251.11.11', 80),
                "Domotics server":   nmap('grafana10.com.diten.unige.it', 7070),
                "Cabinet switch":    nmap('fork', 9000),
                "Webcam":            nmap('ipcam', 554),
            },
            "error": []
        }

        return res


@api.route("/tests")
class Tests(Resource):
    """Test the servers"""

    def get(self):
        """Response from servers"""

        timeout = 0.1

        def req(address, timeout=timeout):

            try:
                res = requests.get(address, timeout=timeout)
                return True if res.status_code == 200 else False
            except requests.exceptions.ConnectionError as e:
                return None
            except requests.exceptions.ConnectTimeout as e:
                return None
            except requests.exceptions.ReadTimeout as e:
                return None

        res = {
            "response": {
                "Ascom server":      req("http://ascom:533/api/v1/switch/0/getswitch?id=1"),
                "Scientific camera": req("http://ccd-sbig/api/VersionNumbers.cgi"),
                "Meteo station":     req("http://fork:5533/api/environment/meteo/clock", timeout=0.1),
                "TCS server":        req("http://fork:5533/api/telescope/coordinates"),
                "All sky camera":    "Boooh",
                "Domotics server":   req("http://fork:5533/api/camera/power"),
                "Cabinet switch":    req("http://fork:5533/api/telescope/power"),
                "Webcam":            req("http://admin:BigBang2021@ipcam/image/jpeg.cgi"),
            },
            "error": []
        }

        return res


############################
# WEB VIEW
############################

web = Namespace('home', description='Home page')


@web.route("/")
class HomeWeb(Resource):
    """Show the home page"""

    def get(self):
        """Load the home page"""

        ping = Ping()
        res = ping.get()
        ping = res["response"]

        ports = Ports()
        res = ports.get()
        ports = res["response"]

        tests = Tests()
        res = tests.get()
        tests = res["response"]

        print(ports)
        data = [ping, ports, tests]

        return make_response(render_template("index.html", data=data))

############################
# STREAM
############################


# from .environment import Environment as env_status


@web.route('/stream')
class Stream(Resource):
    def get(self):

        def inner():
            previous_ts = {}
            previous_init_ts = {}
            previous_ds = {}
            previous_cs = {}
            previous_es = {}
            while True:

                try:
                    sleep(1)

                    ###########################
                    # Stream telescope status #
                    ###########################

                    # Complete for control panel
                    ts = tel_status().get()

                    if previous_ts != ts:
                        yield 'event: telescope\ndata: {}\n\n'.format(json.dumps(ts))
                    previous_ts = ts

                    # Reduced for init panel
                    sub_tel = ["power", "connection", "lamp", "parked",
                               "cover", "offset", "rotator", "error"]

                    init_ts = {k: ts[k] for k in sub_tel if k in ts}

                    if previous_init_ts != init_ts:
                        yield 'event: init_tel\ndata: {}\n\n'.format(json.dumps(init_ts))
                    previous_init_ts = init_ts

                    ######################
                    # Stream dome status #
                    ######################

                    ds = dom_status().get()

                    if previous_ds != ds:
                        yield 'event: dome\ndata: {}\n\n'.format(json.dumps(ds))
                    previous_ds = ds

                    ########################
                    # Stream camera status #
                    ########################

                    cs = cam_status().get()

                    if previous_cs != cs:
                        yield 'event: camera\ndata: {}\n\n'.format(json.dumps(cs))
                    previous_cs = cs

                    # #############################
                    # # Stream environment status #
                    # #############################

                    # es = env_status().get()

                    # if previous_es != es:
                    #     yield 'event: environment\ndata: {}\n\n'.format(es)
                    # previous_es = es

                except GeneratorExit:
                    print(f"Stop streaming status")
                    return

        print("Streaming status...")
        return Response(inner(), mimetype="text/event-stream")
