import cv2
import numpy as np
from ultralytics import YOLO as YOLOv8
import PySimpleGUI as sg

def RemoveBlackBorder(image, shrink=True):
    image = np.array(image)
    
    copyImg = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2HSV_FULL)
    mask = np.zeros(image[:,:,0].shape, dtype=np.uint8)
    mask[(copyImg[:,:,1] > 35)] = 255
    copyImg = cv2.cvtColor(copyImg, cv2.COLOR_HSV2RGB_FULL)
    resROI = cv2.bitwise_and(copyImg, copyImg, mask=mask)
    
    image_gray = cv2.cvtColor(resROI, cv2.COLOR_RGB2GRAY)
    _, thresh = cv2.threshold(image_gray, 0, 255, cv2.THRESH_BINARY)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 15))
    morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
    contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    bigCont = max(contours, key=cv2.contourArea)
    x, y, w, h = cv2.boundingRect(bigCont)
    sfx, sfy =  (w *0.01, h*0.07) if shrink else (0, 0)
    crop = image[y +int(sfy) : y + h - int(sfy), x + int(sfx): x + w - int(sfx)]
    return crop

def RemoveBlackBorder2(image):
    image = np.array(image)
    
    copyImg = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2HSV)
    h = copyImg[:,:,0]
    mask = np.ones(h.shape, dtype=np.uint8) * 255
    th = (25, 175)
    mask[(h > th[0]) & (h < th[1])] = 0
    copyImg = cv2.cvtColor(copyImg, cv2.COLOR_HSV2BGR)
    resROI = cv2.bitwise_and(copyImg, copyImg, mask=mask)
        
    image_gray = cv2.cvtColor(resROI, cv2.COLOR_BGR2GRAY)
    _, thresh = cv2.threshold(image_gray, 0, 255, cv2.THRESH_BINARY)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 15))
    morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
    contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    bigCont = max(contours, key=cv2.contourArea)
    x, y, w, h = cv2.boundingRect(bigCont)
    crop = image[y : y + h, x: x + w ]
    return crop

def LoadAndVeiwImge (Path:str, YOLO:float = None):
    image = np.load(Path)
    image = image.astype(np.uint8)
    
    print(image.shape)
    
    if YOLO > 0:
        YoloModel = YOLOv8(model="RARP_YoloV8_ROI.pt")
        res = YoloModel.predict(image, stream=True)
        
        for r in res:
            conf = r.boxes.conf.cpu().numpy()
            for i, box in enumerate(r.boxes.xyxy.cpu().numpy()):
                if conf[i] > YOLO:
                    box = box.astype(int)
                    print (i, box, conf[i])   
                    #x, y = (box[0], box[1])
                    #xw, yh = (box[2], box[3])
                    cv2.rectangle(image, (box[0],box[1]), (box[2],box[3]), (0, 255, 150*i), 3)
    
    cv2.namedWindow("Output", cv2.WINDOW_NORMAL)
    cv2.resizeWindow("Output", (1024, 720))
    cv2.imshow("Output", image)
    cv2.waitKey(0)
    cv2.destroyAllWindows() 

if __name__ == "__main__":
    sg.theme('LightBlue')
    
    layout = [
        [sg.Text('Image Viewer', size=(40, 1), justification='center', font='Helvetica 20',key='-status-')],
        [sg.Text('Camera number: ', size=(15, 1)), sg.InputText(default_text='',  size=(80, 1),key='-Path-')],
        [sg.Text('YOLO Conf.: ', size=(15, 1)), sg.InputText(default_text='0.40',  size=(20, 1),key='-YOLO-')],
        [sg.Checkbox("RAW Image", default=True, key="-NP_Array_IMG-"), sg.Checkbox("Remove Black Bars Old ver.", default=False, key="-oldVer-")],
        [sg.Image(filename='', key='image')],
        [
            sg.Button('YOLO', size=(10, 1), font='Helvetica 14',key ='-start-'),
            sg.Button('Remove BB', size=(10, 1), font='Helvetica 14',key = '-Remove_BB-'),
            sg.Button('View', size=(10, 1), font='Helvetica 14',key = '-verImg-'),
            sg.Button('Exit', size=(10, 1), font='Helvetica 14', key='-exit-'), 
        ]
    ]
    
    window = sg.Window('Image Viewer',layout, location=(100, 100))
    recording = False
    
    while True:
        try:
            event, vals = window.read(timeout=20)
            match event:
                case None | "-exit-":
                    break
                case "-start-":
                    if vals["-NP_Array_IMG-"]:
                        vals["-YOLO-"] = 0 if vals["-YOLO-"] == "" else vals["-YOLO-"]
                        LoadAndVeiwImge(vals["-Path-"], float(vals["-YOLO-"]))
                    else:
                        sg.popup_error("Only RAW images are accepted *.npy")
                case "-Remove_BB-":
                    image = np.load(vals["-Path-"]) if vals["-NP_Array_IMG-"] else cv2.imread(vals["-Path-"], cv2.IMREAD_COLOR)
                    if vals["-oldVer-"] :
                        image = RemoveBlackBorder(image, False)
                    else:
                        image = RemoveBlackBorder2 (image)
                    cv2.namedWindow("Output", cv2.WINDOW_NORMAL)
                    cv2.resizeWindow("Output", (1024, 720))
                    cv2.imshow("Output", image)
                    cv2.waitKey(0)
                    cv2.destroyAllWindows() 
                case "-verImg-":
                    image = np.load(vals["-Path-"]) if vals["-NP_Array_IMG-"] else cv2.imread(vals["-Path-"], cv2.IMREAD_COLOR)
                    cv2.namedWindow("Output", cv2.WINDOW_NORMAL)
                    cv2.resizeWindow("Output", (1024, 720))
                    cv2.imshow("Output", image)
                    cv2.waitKey(0)
                    cv2.destroyAllWindows() 
                    
        except Exception as e:
            print(e)
            
                
    window.close()
        

