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

# System modules
import json
from time import sleep

# Third-party modules
import subprocess
import requests
from astropy.time import Time
from flask import Response, make_response, render_template, request
from flask_restx import Namespace, Resource, fields

# Custom modules
import devices

from .scheduler import scheduler
from .camera import Status as Cam_Status
from .dome import Status as Dom_Status
from .environment import Status as Env_Status
from .telescope import Status as Tel_Status
from .webcam import Snapshot as Web_Snapshot
from .templates import BobRun as Seq_Status

def req(address, timeout=timeout):

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

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

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

@web.route("/")
class HomeWeb(Resource):
    """Show the home page"""
    
    def get(self):
    
        data = [{}, {}, {}]
        return make_response(render_template("index.html", data=data))

############################
# STREAMS
############################

tel_status = Tel_Status()
dom_status = Dom_Status()
cam_status = Cam_Status()
env_status = Env_Status()
web_snapshot = Web_Snapshot()
seq_status = Seq_Status()

@scheduler.task('interval', seconds=2, id="tel", max_instances=1)
def tel_job():
    try:
        tel_status.get()
        #print(tel_status.last)
    except Exception as e:
        print(f"tel_job probably killed web app: {e}")

@scheduler.task('interval', seconds=2, id="dom", max_instances=1)
def dom_job():
    try:
        dom_status.get()
        #print(dom_status.last)
    except Exception as e:
        print(f"dom_job probably killed web app: {e}")

@scheduler.task('interval', seconds=2, id="cam", max_instances=1)
def cam_job():
    try:
        cam_status.get()
        #print(cam_status.last)
    except Exception as e:
        print(f"cam job probably killed web app: {e}")

@scheduler.task('interval', seconds=60, id="env", max_instances=1)
def env_job():
    try:
        env_status.get()
        #print(env_status.last)
    except SystemExit as e:
        print(f"Env status get error: {e}")
    except Exception as e:
        print(f"env_job probably killed web app: {e}")

@scheduler.task('interval', seconds=0.5, id="ipcam", max_instances=1)
def ipcam_job():
    try:
        web_snapshot.get()
        #print(web_snapshot.last)
    except SystemExit as e:
        print(f"Webcam status get error: {e}")
    except RuntimeError as e:
        print(f"ipcam_job probably killed web app: {e}")

@scheduler.task('interval', seconds=2, id="seq", max_instances=1)
def seq_job():
    try:
        seq_status.get()
        #print(cam_status.last)
    except Exception as e:
        print(f"seq_job probably killed web app: {e}")


@web.route('/stream/status')
class StreamStatus(Resource):

    def get(self):

        def inner():

            previous_ts = {}
            previous_ds = {}
            previous_cs = {}
            previous_sq = {}

            while True:

                try:
                    sleep(1)

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

                    # Complete for control panel
                    ts = tel_status.last

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

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

                    ds = dom_status.last

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

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

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

                    ###########################
                    # Stream sequencer status #
                    ###########################

                    sq = seq_status.last
                    #print(sq)
                    if previous_sq != sq:
                        yield 'event: sequencer\ndata: {}\n\n'.format(json.dumps(sq))
                    previous_sq = sq

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

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


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

        def inner():
            previous_es = {}
            while True:

                try:
                    sleep(20)

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

                    es = env_status.last

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

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

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



@web.route('/stream/webcam')
class StreamWebcam(Resource):
    def get(self):
        def inner():
            while True:

                try:
                    sleep(0.5)

                    ##########################
                    # Stream webcam snapshot #
                    ##########################

                    img = web_snapshot.last
                    if img:
                        yield (b'--frame\r\n'
                               b'Content-Type: image/jpeg\r\n\r\n' + img + b'\r\n')

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

        return Response(inner(), mimetype="multipart/x-mixed-replace; boundary=frame")


@web.route('/stream/logfile')
class StreamLogfile(Resource):
    def get(self):
        def inner(today):

            proc = subprocess.Popen(
                [f"tail -f -n30 ./data/log/OARPAF.{today}.log"],
                shell=True,
                stdout=subprocess.PIPE
            )

            try:

                for line in iter(proc.stdout.readline, ''):
                    line = line.rstrip().decode()

                    if not line:
                        sleep(0.05)
                        yield "event: logfile\ndata: \n\n"
                        continue

                    sleep(0.05)
                    yield f"event: logfile\ndata: {line}\n\n"

            except GeneratorExit:
                print("qui")
                print("Stop streaming log")
                print("Closing subprocess")
                proc.terminate()
                proc.wait()
                print("Subprocess closed")

        print("Streaming template log...")
        today = Time.now().iso.split()[0]
        return Response(inner(today), mimetype="text/event-stream")
