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

from flask import render_template, make_response, request
from flask_restx import Namespace, Resource

from .devices_access_object import RtcObject as DAO

RTC = DAO()


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

api = Namespace('rtc', description='Real Time Control')

@api.route("/centroid")
class Centroid(Resource):

    def get(self):
        return RTC.centroid

    def put(self):
        cx_cy = api.payload
        RTC.centroid = list(map(float, cx_cy))

@api.route("/shape")
class Shape(Resource):

    def delete(self):
        return RTC.flatten()

@api.route("/loop")
class Loop(Resource):

    def post(self):
        return RTC.close_loop()

    def delete(self):
        return RTC.open_loop()

@api.route("/patrol")
class Size(Resource):

    def post(self):
        return RTC.patrol(True)

    def delete(self):
        return RTC.patrol(False)

@api.route("/frequency")
class Frequency(Resource):

    def put(self):
        freq = api.payload
        return RTC.frequency(freq)

@api.route("/temperature")
class Temperature(Resource):

    def put(self):
        temp = api.payload
        return RTC.temperature(temp)

@api.route("/pid")
class Pid(Resource):

    def put(self):
        pid = api.payload
        return RTC.pid(pid)
    
@api.route("/threshold")
class Pid(Resource):

    def get(self):
        return RTC.get_threshold()

    def put(self):
        threshold = api.payload
        return RTC.threshold(threshold)
    
@api.route("/exptime")
class Exptime(Resource):

    def put(self):
        temp = api.payload
        return RTC.tint(temp)

@api.route("/dark")
class Dark(Resource):

    def get(self):
        return RTC.todos_dark

    def put(self):
        name = api.payload
        return RTC.load_dark(name)

    def post(self):
        return RTC.new_dark()

    # def delete(self):
    #     subtract = api.payload
    #     return RTC.subtract_dark()

@api.route("/flat")
class Flat(Resource):

    def get(self):
        return RTC.todos_flat

    def put(self):
        name = api.payload
        print(name)
        return RTC.load_flat(name)

    def post(self):
        return RTC.save_flat()

@api.route("/gain")
class Gain(Resource):

    def get(self):
        return RTC.todos_gain

    def put(self):
        name = api.payload
        return RTC.load_gain(name)

    def post(self):
        gain_type, centroid_size = api.payload
        return RTC.new_gain(gain_type, centroid_size)

@api.route("/tiptilt")
class TipTilt(Resource):

    # def get(self):
    #     return RTC.todos

    def put(self):
        modes = api.payload
        if modes == None:
            return RTC.tiptilt( absolute=True )
        else:
            return RTC.tiptilt( list(map(float, modes)) )

@api.route("/teccam")
class Teccam(Resource):

    def post(self):
        return RTC.teccam_http_start()

    def put(self):
        return RTC.teccam_custom_command(api.payload)


@api.route("/plots/")
class PlotListApi(Resource):

    def get(self):
        """Show RTC related data"""        
        data = RTC.data()
        
        return data

    # def post(self):
    #     return RTC.create(api.payload), 201


@api.route("/file")
class PlotListApi(Resource):

    def post(self):
        """Show RTC related data"""
        
        filename = RTC.save()
        
        return filename

    
@api.route("/plots/<int:id>")
class PlotApi(Resource):

    def get(self, id):
        return RTC.read(id)

    # def delete(self, id):
    #     RTC.delete(id)
    #     return "", 204

    def put(self, id):
        return RTC.update(id, api.payload)

@api.route("/samples")
class SamplesApi(Resource):

    def put(self):
        return RTC.cloud_samples(float(api.payload))

    def get(self):
        return RTC.get_cloud_samples()
    
@api.route("/reset")
class ResetApi(Resource):

    def post(self):
        return RTC.reset()

@api.route("/resurrect")
class ResurrectApi(Resource):

    def post(self):
        #return RTC.resurrect()
        return RTC.resurrect2()

@api.route("/soul/movement")
class SoulMovementApi(Resource):

    def put(self):
        soul_pos = api.payload
        output = RTC.move_soul(soul_pos, apply_movement=True)
        print("PUT Received this: {}".format(output))
        if not output[0]:
            return output, 200
        else:
            return output, 400
    def post(self):
        soul_pos = api.payload
        output = RTC.move_soul(soul_pos, apply_movement=False)
        print("POST Received this: {}".format(output))
        if not output[0]:
            return output, 200
        else:
            return output, 400

@api.route("/mode")
class ModeApi(Resource):

    def post(self):
        mode = api.payload
        status = RTC.uploadRTC(mode)
        if not status:
            return status, 200
        else:
            return status, 400
        
@api.route("/mode/zonal")              #("/zonalMovement")
class ModeZonalApi(Resource):

    def put(self):
        cmd = api.payload
        status = RTC.zonalCommand(cmd)
        if not status:
            return status, 200
        else:
            return status, 400

@api.route("/derotation")  # poi dovrá cambiare in bearing/derotation, non apparterrá più all'api rtc
class Derotation(Resource):

    def put(self):
        cmd = api.payload
        print("rtc.py -_____________________________-{}".format(cmd))
        return RTC.manageDerotation(cmd)

@api.route("/mode/rotation")          #("/ncpa_rotation")
class ModeRotationApi(Resource):
    
    def put(self):
        action_start = api.payload
        return RTC.rotateNCPA(action_start)
    
    def delete(self):
        action_stop = api.payload
        return RTC.rotateNCPA(action_stop)

    def get(self):
        return RTC.getNCPARotationStatus()

@api.route("/mode/ncpa")
class Ncpa(Resource):

    def get(self):
        print("qui GET 'mode/ncpa' rtc.py")
        return RTC.todos_flat

    def put(self):
        print("qui PUT 'mode/ncpa' rtc.py")
        name = api.payload
        print(name)
        return RTC.load_ncpa(name)

    def post(self):
        return RTC.save_ncpa()

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

RTC.create({"name": "CRED2 image",
            "id":   "cred",
            "info": [
                ("min", "image min (counts)"),
                ("max", "image max (counts)"),
                ("mean_flux", "mean flux (counts)"),
                ("tot_flux", "8x8 around rtc centr (counts/frame)"),
                ]
            })

RTC.create({"name": "Mirror shape",
            "id":   "dm",
            "info": [
                ("min", "actuator min"),
                ("max", "actuator max"),
                ("skp_cmd", "# skipped comands")
                ]
            })

RTC.create({"name": "Mirror shape without flat",
            "id":   "dm2",
            "info": [
                ("min", "actuator min"),
                ("max", "actuator max"),
                ]
            })

RTC.create({"name": "Centroid cloud",
            "id":   "cloud",
            "info": [
                ("min", "histo min (counts)"),
                ("max", "histo max (counts)"),
                ("wx", "PtV x (mas)"),
                ("wy", "PtV y (mas)"),
                ("RMS_X", "RMS x (mas)"),
                ("RMS_Y", "RMS y (mas)"),
                ("cloud_samples", "Samples (#)"),
                ]
            })

web = Namespace('rtc', description='Real Time Control')

@web.route("/")
class Test(Resource):

    def get(self):
        data = RTC.todos
        darks = RTC.todos_dark()
        gains = RTC.todos_gain()
        flats = RTC.todos_flat()
        ncpas = RTC.todos_ncpa()
        return make_response(render_template("rtc_panel.html", data=data, darks=darks, flats=flats, gains=gains, ncpas=ncpas))

@web.route("/controls/")
class RtcControlsListWeb(Resource):

    def get(self):
        darks = RTC.todos_dark()
        gains = RTC.todos_gain()
        flats = RTC.todos_flat()
        ncpas = RTC.todos_ncpa()
        return make_response(render_template("rtc_controls.html", darks=darks, flats=flats, gains=gains, ncpas=ncpas))

@web.route("/plots/")
class RtcPlotsListWeb(Resource):

    def get(self):
        data = RTC.todos
        return make_response(render_template("rtc_plots.html", data=data))

@web.route("/plots/<id>")
class RtcPlotsWeb(Resource):

    def get(self,id):
        data = [RTC.read(id)]
        return make_response(render_template("rtc_plots.html", data=data))



############################
# Stream
############################
    
from flask import Response
import json
import time
from .scheduler import this_scheduler


@this_scheduler.task('interval', seconds=0.5)
def update_rtc_data():
    RTC.data()
      
@web.route('/stream')
class Stream(Resource):
    def get(self):
        def inner():

            previous_res = {}            
            
            while True:
                try:
                    time.sleep(0.2)
                    resource = RTC.json_state
                    if previous_res != resource:
                        yield 'data: {}\n\n'.format(json.dumps(resource))
                    else:
                        print("Data are the same as before")
                    #previous_res = resource     #da ripristinare                        
                except GeneratorExit:
                    print("Stop streaming rtc data")
                    return
                
        response = inner()
        print("Streaming rtc data...")

        return Response(response, mimetype="text/event-stream")
