from datetime import datetime
from FrameBuffer import FrameBuffer
import cv2
# import random
# RTSP-Stream-URL einstellen
#1280x720:
#rtsp_url = "rtsp://admin:RlBqOp30cam@192.168.178.121/live/ch0"
#640x360:
rtsp_url = "rtsp://admin:RlBqOp30cam@192.168.178.121/live/ch1"

# OpenCV-Videoaufzeichnungsobjekt erstellen
cap = cv2.VideoCapture(rtsp_url)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print("Width: "+str(width)+" Height: "+str(height))
fps = cap.get(cv2.CAP_PROP_FPS)
print(f'Framerate: {fps}')
# 2 Sekunden vor Erkennung
MAX_BUFFER = fps*2
# Codec für die Ausgabe festlegen
fourcc = cv2.VideoWriter_fourcc(*'XVID')
frameBuffer = FrameBuffer(MAX_BUFFER)
# Initialisiere den Hintergrundsubtraktor
# Load the mask from a file
# mask_file = 'CAM2maskeBW.png'
mask_file = 'CAM2maskeBW640.png'
mask_rgb = cv2.imread(mask_file)
mask = cv2.imread(mask_file, cv2.IMREAD_GRAYSCALE)
# Invert the mask (if necessary) and threshold it
# mask = cv2.bitwise_not(mask)
mask = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)[1]
# Ausgabedatei erstellen und Videoaufzeichnung starten
# output_file = cv2.VideoWriter('output.avi', fourcc, 20.0, (640,480))
counter = 1
# print(datetime.datetime.now().time())
firstFrameWithMotion = 0
lastFrameWithMotion = 0
fgbg = cv2.createBackgroundSubtractorMOG2()
bufferedFrames = []
while(cap.isOpened()):
    try:
        ret, frame = cap.read()
        if ret:
            #output_file.write(frame)
            #img = cv2.imread(frame)
            # Wende die Maske auf das Frame an
            masked_frame = cv2.bitwise_and(frame, frame, mask=mask)

            # Subtrahiere das Hintergrund-Modell von dem aktuellen Frame
            fgmask = fgbg.apply(masked_frame)
            #gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            #fgmask = fgbg.apply(gray)
            blur = cv2.GaussianBlur(fgmask, (5,5), 0)
            ret,thresh = cv2.threshold(blur,100,255,cv2.THRESH_BINARY)
            kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
            opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations = 3)
            contours, hierarchy = cv2.findContours(opening, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

            for c in contours:
                area = cv2.contourArea(c)
                faktor = (width*height*4)/(640*360)
                #if area > width*height/3 or area < width*height/20:
                #    continue
                if area < 1600*faktor or area > 40000*faktor:
                    continue
                (x, y, w, h) = cv2.boundingRect(c)
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
                if firstFrameWithMotion == 0:
                    firstFrameWithMotion = counter
                    lastFrameWithMotion = counter
                    bufferedFrames = frameBuffer.get_frames()
                if firstFrameWithMotion > 0:
                    lastFrameWithMotion = counter

            MAX_PAUSE_OF_MOTION = fps/2
            MIN_DURATION_OF_MOTION = fps*2
            WATCH_BEFORE = fps*2
            if firstFrameWithMotion > 0 and lastFrameWithMotion - firstFrameWithMotion > MIN_DURATION_OF_MOTION and counter - lastFrameWithMotion > MAX_PAUSE_OF_MOTION:

                fourcc = cv2.VideoWriter_fourcc(*'mp4v')
                now = datetime.now()
                # Format the date and time as a string
                dt_string = now.strftime("%Y-%m-%d_%H-%M-%S")
                print(dt_string + " Schreibe mp4 Datei")
                out = cv2.VideoWriter("output-" + dt_string + ".mp4", fourcc, fps, frameSize=(width, height))
                for frame in bufferedFrames:
                    out.write(frame)
                out.release()
                firstFrameWithMotion = 0
                lastFrameWithMotion = 0
                frameBuffer.dump()
                bufferedFrames = []

            if counter > MAX_BUFFER and firstFrameWithMotion == 0:
                counter = 1

            # Apply the mask to the frame
            #masked_frame = cv2.multiply(0.2, mask_rgb) + frame

            cv2.imshow('frame',frame)
            #cv2.imshow('fgmask',fgmask)
            if firstFrameWithMotion == 0:
                frameBuffer.push(frame)
            else:
                bufferedFrames.append(frame)
            #if counter % 10 == 0:
            #    print("Frame"+str(counter))
            counter += 1


            #blur_img = cv2.GaussianBlur(frame, (5, 5), 0)
            #cv2.imshow('frame',blur_img)
            #edges = cv2.Canny(blur_img, 150, 200)
            #cv2.imshow("Kantenerkennung", edges)

            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        else:
            break
    except Exception as e:
        # Hier kommt der Code, der ausgeführt wird, wenn ein Fehler auftritt
        print("Ein Fehler ist aufgetreten:", str(e))

# Freigeben der Ressourcen
cap.release()
cv2.destroyAllWindows()