from datetime import datetime

from typing import Optional
import os

import sys
import threading

from deepface.basemodels.SFace import cv

import requests


from deepface import DeepFace


import cv2


import matplotlib.pyplot as plt


import numpy as np
import pandas as pd


from glob import glob


import cv2


from deepface import DeepFace
import pandas as pd


import matplotlib.pyplot as plt


import numpy as np


import docker


user_profile = os.environ['USERPROFILE']


SEP = os.path.sep


LOGO_URL = "https://raw.githubusercontent.com/codesapienbe/aij-webcam/master/logo.png"


SCREEN_WIDTH = 1280


SCREEN_HEIGHT = 720


SCREEN_FPS = 30


SCREEN_START_X = 0


SCREEN_START_Y = 0


SCREEN_MAXIMIZE = True


APP_TITLE = 'AIJ'


start = datetime.now().strftime("%Y%m%d%H%M%S")

start_dt = datetime.now()

config_home = user_profile + SEP + '.aij'

config_abs = config_home + SEP + 'config.json'

image_home = user_profile + SEP + '.aij' + SEP + 'image'

logo_abs = image_home + SEP + 'logo.png'

csv_home = user_profile + SEP + '.aij' + SEP + 'news'

csv_abs = csv_home + SEP + 'news.csv'

audio_home = user_profile + SEP + '.aij' + SEP + 'audio'

screenshot_home = user_profile + SEP + '.aij' + SEP + 'screenshot'

audio_abs = audio_home + SEP + start + '.mp3'

video_home = user_profile + SEP + '.aij' + SEP + 'video'

face_home = user_profile + SEP + '.aij' + SEP + 'face'

news_df = Optional[pd.DataFrame]

weather_df = Optional[pd.DataFrame]


backends = [



    "opencv",
    "ssd",



    "dlib",
    "mtcnn",
    "retinaface",
    "mediapipe"



]


default_backend = backends[0]


models = [



    "VGG-Face",


    "Facenet",



    "Facenet512",



    "OpenFace",



    "DeepFace",



    "DeepID",



    "ArcFace",



    "Dlib",



    "SFace",



]


default_model = models[0]


def pre_init():
    """
    This function is called before the server is initialized
    """

    client = docker.from_env()

    # print all containers

    containers = client.containers.list()

    for container in containers:

        print(
            container.name,
            container.id,
            container.status
        )

    # if there is no docker container running named aij-messaging-server then run the server script 'aijinit'

    if not any(container.name == 'aij-messaging-server' for container in containers):

        os.system('aijinit')


def download_logo():
    """
    Download the logo.png file to userprofile/.aij/images/logo.png
    """

    logo_remote_response = requests.get(
        LOGO_URL, allow_redirects=True, stream=True, timeout=10)

    if logo_remote_response.status_code == 200:

        # save the logo.png file if the response is ok and the file does not exist

        if not os.path.exists(logo_abs):

            with open(logo_abs, 'wb') as logo_file:

                logo_file.write(logo_remote_response.content)


def draw_text(image, x, y, text, color):
    """

    Draw text on the image
    """

    # draw a black rectangle on the image

    cv2.rectangle(
        image,

        (x, y - 25),

        # until the end of screen width

        (x + image.shape[1], y),

        (0, 0, 0),

        -1

    )

    # draw the text on the image

    cv2.putText(
        image,

        text,

        (x, y),

        cv2.FONT_HERSHEY_SIMPLEX,

        font_size / 12,
        color,

        2,

        cv2.LINE_AA

    )


def draw_box(image, x, y, color):
    """

    Draw a box on the image
    """

    cv2.rectangle(
        image,

        (x, y),

        (x + box_size, y + box_size),
        color,

        2

    )


def draw_button(image, x, y, text, color):
    """

    Draw a button on the image and write text on it
    """

    cv2.rectangle(
        image,

        (x, y),

        (x + box_size, y + box_size),
        color,

        2

    )

    cv2.putText(
        image,

        text,

        (x + 5, y + 30),

        cv2.FONT_HERSHEY_SIMPLEX,

        font_size,
        color,

        2,

        cv2.LINE_AA

    )


def draw_zoomed_text(image, x, y, text, color):
    """

    Draw zoomed text on the image
    """

    cv2.putText(
        image,

        text,

        (x, y),

        cv2.FONT_HERSHEY_SIMPLEX,

        font_size,
        color,

        2,

        cv2.LINE_AA

    )


def draw_logo(logo_path, img):
    if os.path.exists(logo_path):

        logo = cv2.imread(logo_path)

        # Resize the logo to match the height of the main image and keep the aspect ratio

        # resize the logo to 100px height and keep the aspect ratio

        logo_resized = cv2.resize(
            logo, (48, 48), interpolation=cv2.INTER_AREA)

        # get the height and width of the logo

        logo_height, logo_width, _ = logo_resized.shape

        # calculate the x and y coordinates of the logo

        x = 5

        y = 5

        # draw the logo on the main image

        img[y:y + logo_height, x:x + logo_width] = logo_resized

        return img


def draw_emoji(current_emotion, img):
    emoji_home = user_profile + SEP + '.aij' + SEP + 'emojis'

    # find all emojis
    matching_emoji = [emoji for emoji in os.listdir(emoji_home) if emoji.endswith(
        ".png") and emoji.startswith(current_emotion)]
    emj = cv2.imread(emoji_home + SEP + matching_emoji[0])

    # resize the emj to 64px height and keep the aspect ratio
    emj_resized = cv2.resize(emj, (64, 64), interpolation=cv2.INTER_AREA)

    # get the height and width of the emj

    emj_height, emj_width, _ = emj_resized.shape

    # get the height and width of the main image

    image_height, image_width, _ = img.shape

    # calculate the x and y coordinates of the emj

    x = image_width - emj_width - 5

    y = image_height - emj_height - 5

    # draw the emj on the main image

    img[y:y + emj_height, x:x + emj_width] = emj_resized

    return img


# do not wait for the directories to be created
thread_download_logo = threading.Thread(target=download_logo)

thread_download_logo.start()


default_backend = "opencv"


default_model = "VGG-Face"


cam = cv2.VideoCapture(0)


# set the width and height, and UNSUCCESSFULLY set the exposure time


cam.set(cv2.CAP_PROP_FRAME_WIDTH, SCREEN_WIDTH)


cam.set(cv2.CAP_PROP_FRAME_HEIGHT, SCREEN_HEIGHT)


cam.set(cv2.CAP_PROP_FPS, SCREEN_FPS)


# Define min window size to be recognized as a face


MIN_FACE_FRAME_WIDTH = 50


MIN_FACE_FRAME_HEIGHT = 50


FRAME_COUNTER = 0

current_emotion = "neutral"


while cam.isOpened():

    ret, img = cam.read()

    img = cv2.flip(img, 1)  # Flip vertically

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # increase the frame counter

    FRAME_COUNTER += 1

    try:

        # after each 5 seconds detect faces

        if FRAME_COUNTER >= SCREEN_FPS:

            # reset the frame counter

            FRAME_COUNTER = 0

            # predict the emotion

            emotion = DeepFace.analyze(img_path=img, actions=[


                'emotion'], detector_backend=default_backend, align=True, silent=True)

            # get the emotion data from the dictionary

            emotion_data = emotion[0]['emotion']

            # convert to dataframe

            emotion_df = pd.DataFrame(emotion_data, index=[0])

            # get the dominant emotion

            emotion_label = emotion_df.idxmax(axis=1)[0]

            # add the emotion to the emotion history
            current_emotion = emotion_label

    except Exception as e:

        # draw error message if no face detected
        pass

    img = draw_emoji(current_emotion, img)

    img = draw_logo(logo_abs, img)

    cv2.imshow('Emotion Recognition', img)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        cam.release()
        break


if cam.isOpened():
    cam.release()

cv2.destroyAllWindows()
