from PIL import Image
from io import BytesIO

from flask import Flask, request, make_response, abort, render_template
from flask_restful import Api, Resource

import base
import rest
import auth
from config import cfg

from camera import Camera

app = Flask(__name__)
api = Api(app)


@app.route("/", methods=["POST"])
def default():
    token = request.form.get("token")
    if token == "": abort(401)
    print(token)
    if not auth.checktoken(token): abort(401)

    return render_template("apiinfo.html")


class CameraController(Resource):
    def put(self):
        token = request.headers.get('Authorization')
        if not auth.checktoken(token):
            return make_response('authorized failed', 401)

        if Camera.IsOpened():
            return make_response("success")
            
        if Camera.OpenCamera():
            return make_response("success")
        else:
            return make_response('open camera failed', 500)

    
    def delete(self):
        token = request.headers.get('Authorization')
        if not auth.checktoken(token):
            return make_response('authorized failed', 401)

        if not Camera.IsOpened():
            return make_response("success")
            
        Camera.CloseCamera()
        return make_response("success")


class CaptureImage(Resource):
    def get(self):
        token = request.headers.get('Authorization')
        if not auth.checktoken(token):
            return make_response('authorized failed', 401)
        
        (hr, image) = Camera.CaptureImageBuf()
        if hr == -1 :
            return make_response('camera is not opened', 400)
        elif hr == -2:
            return make_response('capture image failed', 500)
            
        # change ndarray into jpg bytes flow
        bio = BytesIO()          
        img = Image.fromarray(image)
        img.save(bio, format="jpeg")
        
        response = make_response(bio.getvalue())
        response.headers["Content-Disposition"] = "attachment; filename=capture.jpg"
        response.headers["Content-type"] = "image/jpeg"
        return response


    def post(self):
        token = request.headers.get('Authorization')
        if not auth.checktoken(token):
            return make_response('authorized failed', 401)
                    
        reqjson = request.get_json()
        directory = reqjson["directory"]
        filename = reqjson["filename"]
        if directory is None or filename is None:
            return make_response('miss parameters', 400)
            
        hr = Camera.CaptureImage(directory, filename)
        if hr == 0 :
            return make_response('success')
        elif hr == -1 :
            return make_response('camera is not opened', 400)
        elif hr == -2:
            return make_response('get image from camera failed', 500)
        else:
            return make_response('save image to folder failed', 500)


class CaptureImages(Resource):
    def put(self):
        token = request.headers.get('Authorization')
        if not auth.checktoken(token):
            return make_response('authorized failed', 401)
            
        reqjson = request.get_json()
        directory = reqjson["directory"]
        prename = reqjson["prename"]
        bufsize = reqjson["bufsize"]
        duration = reqjson["duration"]
        if directory is None or prename is None or bufsize is None or duration is None:
            return make_response('miss parameters', 400)
        if bufsize < 10 or duration < 0.5:
            return make_response('miss parameters', 400)

        hr = Camera.CaptureImagesStart(directory, prename, bufsize, duration)
        if hr == 0 :
            return make_response('success')
        elif hr == -1 :
            return make_response('camera is not opened', 400)
        elif hr == -2 :
            return make_response('capture-thread is running.', 400)
        else :
            return make_response('start capture-thread failed.', 500)

    
    def delete(self):
        token = request.headers.get('Authorization')
        if not auth.checktoken(token):
            return make_response('authorized failed', 401)

        hr = Camera.CaptureImagesStop()
        if hr == 0 :
            return make_response('success')
        
        return make_response('stop capture-thread failed.', 500)


api.add_resource(CameraController, '/camera')
api.add_resource(CaptureImage, '/image/capture')
api.add_resource(CaptureImages, '/images/capture')

if __name__ == '__main__':
    port = cfg.getint("server","port")
    
    app.run(
        host = '0.0.0.0',
        port = port,
        debug = False
    )