import glob
import os
import pytesseract
import re
import torch
import ultralytics
from ultralytics import YOLO
from PIL import Image
#ultralytics.checks()
from xml.etree import ElementTree as ET
from .consts import  BASE_PATH

if torch.cuda.is_available():
    device = torch.device('cuda')
else:
    device = torch.device('cpu')

def convert_bbox_to_yolo(
    size: tuple[float, float], box: tuple[float, float, float, float]
) -> tuple[float, float, float, float]:
    """Convert bounding box from absolute coordinates to relative coordinates.

    :param size: Tuple of (width, height) of the image.
    :param box: Tuple of (xmin, ymin, xmax, ymax) for the bounding box.
    :return: Tuple of (x_center, y_center, width, height) in relative
        coordinates.
    """
    scale_width = 1.0 / size[0]
    scale_height = 1.0 / size[1]

    center_x = (box[0] + box[2]) / 2.0
    center_y = (box[1] + box[3]) / 2.0
    box_width = box[2] - box[0]
    box_height = box[3] - box[1]

    rel_center_x = center_x * scale_width
    rel_center_y = center_y * scale_height
    rel_width = box_width * scale_width
    rel_height = box_height * scale_height

    return (rel_center_x, rel_center_y, rel_width, rel_height)
def xml_to_txt(input_xml: str, output_txt: str, class_mapping: dict[str, int]):
    """Parse an XML file and write to a .txt file in YOLO format.

    :param input_xml: Path to the input XML file.
    :param output_txt: Path to the output .txt file.
    :param class_mapping: Dictionary mapping class names to class.
    """
    tree = ET.parse(input_xml)
    root = tree.getroot()
    width = int(root.find(".//size/width").text)
    height = int(root.find(".//size/height").text)

    with open(output_txt, "w", encoding="utf-8") as txt_file:
        for obj in root.iter("object"):
            cell_name = obj.find("name").text
            cell_id = class_mapping.get(cell_name, -1)

            if cell_id == -1:
                continue

            xmlbox = obj.find("bndbox")
            box = (
                float(xmlbox.find("xmin").text),
                float(xmlbox.find("ymin").text),
                float(xmlbox.find("xmax").text),
                float(xmlbox.find("ymax").text),
            )
            bbox = convert_bbox_to_yolo((width, height), box)
            txt_file.write(f"{cell_id} {' '.join([str(a) for a in bbox])}\n")


def download_kaggle_data():
    import kagglehub
    if not os.path.exists(f"{BASE_PATH}/data/indian-number-plates-dataset"):
        # Download latest version
        path = kagglehub.dataset_download("dataclusterlabs/indian-number-plates-dataset")
        print("Path to dataset files:", path)

def convert_to_yolo_format(data_path):
    import glob
    files = glob.glob(data_path + '/*.xml')
    print(len(files))
    for xml_fil in files:
        if not os.path.isdir(xml_fil):
            txt_fil = xml_fil.split('.')[:-1]
            txt_fil = '.'.join(txt_fil) + '.txt'
            xml_to_txt(xml_fil, txt_fil, class_mapping = {'number_plate': '0'})
    files = glob.glob(data_path + '/*.txt')
    print(len(files))

def train_model():
    from ultralytics.data.dataset import YOLODataset
    dataset = YOLODataset(img_path=f"{BASE_PATH}/data/train/images", data={"names": {0: "person"}}, task="detect")
    dataset.get_labels()
    
    model = YOLO(f"{BASE_PATH}/models/yolov8n.pt")
    results = model.train(data=f'{BASE_PATH}/data/data.yaml', epochs=50, imgsz=1728)
    
    model.export(format='onnx', dynamic=True,
                 #path = "../models/yolov8n_anpr.onnx",
                 simplify=True, device=device)

def infer(filename):
    model2 = YOLO(f"{BASE_PATH}/models/train25/best.pt")
    test_result = model2.predict(source=filename)
    #onnx_model = YOLO("../models/train25/best.onnx")
    #model_2 = YOLO('/kaggle/input/weights/best(2).pt')
    #testfiles = glob.glob('../data/TEST/*')
    #import pdb; pdb.set_trace()
    #test_result = model2.predict(source=testfiles[4])
    number_plates = dict()
    for i, res in enumerate(test_result):
        res_img = res.plot()
        plate_im = Image.fromarray(res_img)
        np_text = pytesseract.image_to_string(plate_im, lang='eng')
        plate = str("".join(re.split("[^a-zA-Z0-9]*", np_text)))
        number_plates[i] = plate.upper()
    return number_plates

#download_kaggle_data()
#data_path = '../data/train/labels'
#convert_to_yolo_format(data_path)
#data_path = '../data/TEST/labels'
#convert_to_yolo_format(data_path)
#train_model()
