import flask
from flask_cors import CORS
from flask import Flask, jsonify, request, redirect
import tensorflow.keras
from PIL import Image, ImageOps
import dlib
import cv2
import numpy as np
import os
import base64
import uuid


app = Flask(__name__)
CORS(app)
face_liveness_threshold = 0.7
@app.route("/VerifyFaceLiveness", methods=["GET", "POST"])
def VerifyFaceLiveness():
    try:
        sImagePath = "D:\\GIT\\TFaceAuth\\tfacerecognition\\Windows\\TFaceAuthServer\\Images\\Liveness\\"
        print("VerifyFaceLiveness: ")
        face_livenessData = request.json["facedata"]
        sourceFaceImage = sImagePath
        sourceFaceImage = sourceFaceImage + str(uuid.uuid4())+"_live"+".png"
        with open(sourceFaceImage, "wb") as fh:
            fh.write(base64.b64decode(face_livenessData))
        liveness_data = detect_liveness(sourceFaceImage,True)
        return liveness_data
    except Exception as identifier:
        print("Exception in VerifyFaceLiveness: "+str(identifier))
        return jsonify("Oops! Something went wrong")


def detect_faces(image, name):
    try:
        print("detect_faces " + str(name))
        # Create a face detector
        face_detector = dlib.get_frontal_face_detector()

        # Run detector and get bounding boxes of the faces on image.
        detected_faces = face_detector(image, 1)
        print("Number of faces detected: {}".format(
            len(detected_faces)))
        for i, d in enumerate(detected_faces):
            print(
                "Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
                    i, d.left(), d.top(), d.right(), d.bottom()
                )
            )
            img = cv2.imread(name)
            crop = img[d.top(): d.bottom(), d.left(): d.right()]
            resize = cv2.resize(crop, (200, 200))
            cv2.imwrite(name, resize)
            cv2.waitKey(0)
    except Exception as identifier:
        print("Exception in detect_faces " + str(identifier))


def detect_liveness(imagename,isReturnJson):
    try:
        print("detect_liveness" + str(imagename))
        image = dlib.load_rgb_image(imagename)
        detected_faces = detect_faces(image, imagename)
        # Disable scientific notation for clarity
        np.set_printoptions(suppress=True)

        # Load the model
        model = tensorflow.keras.models.load_model("keras_model.h5")

        # Create the array of the right shape to feed into the keras model
        # The 'length' or number of images you can put into the array is
        # determined by the first position in the shape tuple, in this case 1.
        data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32)

        # Replace this with the path to your image
        image = Image.open(imagename)

        # resize the image to a 224x224 with the same strategy as in TM2:
        # resizing the image to be at least 224x224 and then cropping from the center
        size = (224, 224)
        image = ImageOps.fit(image, size, Image.ANTIALIAS)

        # turn the image into a numpy array
        image_array = np.asarray(image)

        # Normalize the image
        normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1

        # Load the image into the array
        data[0] = normalized_image_array

        # run the inference
        prediction = model.predict(data)
        print(prediction)
        real = prediction[0][0]
        fake = prediction[0][1]
        if isReturnJson:
            if abs(real) >= face_liveness_threshold:
                # return Real Face
                return jsonify("Real Face")
            elif abs(fake)>= face_liveness_threshold:
                # return Fake Face
                return jsonify("Fake Face")
            else:
                # return Not Sure
                return jsonify("Not Sure")
        if abs(real) >= face_liveness_threshold:
            return True
        else:
            return False
        return real, fake
    except Exception as identifier:
        print("Exception in detect_liveness " + str(identifier))

if __name__ == "__main__":
    app.run()