#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import pandas as pd
import numpy as np
import concurrent.futures

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

from skimage import io, img_as_float32, color, img_as_ubyte, morphology
from skimage.color import rgb2gray
from skimage.measure import label, regionprops
from skimage.morphology import convex_hull_object
from skimage.filters import threshold_otsu
from skimage.util import invert


def analyze_one_image(file_path, output_folder, min_area=4000):
    """
    Analyse une image *_cor.png* :
      1. Lecture de l’image (full-res).
      2. Conversion niveaux de gris + seuillage d’Otsu.
      3. Closing morphologique + enveloppe convexe.
      4. Analyse des composantes (aire ≥ min_area) et génération de :
         • un masque « convex hull »
         • une figure overlay haute def avec bbox & centroïdes.
      5. Retourne les métriques (list[dict]) pour le CSV.

    Chaque dictionnaire contient :
      Label, num_label, perimeter, area,
      profondeur, largeur, y_top, y_bottom
    """
    filename = os.path.basename(file_path)
    filename_no_ext = filename[:-4]                     # « .png » → ""

    # ---------- 1) Lecture ----------
    read_img = io.imread(file_path)
    # Conversion RGBA → RGB si canal alpha
    if read_img.shape[-1] == 4:
        read_img = color.rgba2rgb(read_img)

    read_img = img_as_float32(read_img)
    read_img = np.uint8(read_img * 255)

    # ---------- 2) Gris + seuillage ----------
    img_gray = rgb2gray(read_img)
    thresh   = threshold_otsu(img_gray)
    bin_img  = invert(img_gray > thresh)                # Inversion ⇒ objet = True

    # Closing pour combler les trous
    closed_img = morphology.binary_closing(bin_img, morphology.disk(40)).astype(bool)

    # ---------- 3) Enveloppe convexe ----------
    chull = convex_hull_object(closed_img)

    # Sauvegarde du masque convex hull (noir/blanc inversion)
    output_mask = os.path.join(output_folder, f"{filename_no_ext}_convex_hull.png")
    io.imsave(output_mask, invert(img_as_ubyte(chull)))

    # ---------- 4) Analyse & figure ----------
    label_image = label(chull)
    regions     = regionprops(label_image)

    fig, axes = plt.subplots(1, 2, figsize=(12, 6))
    ax = axes.ravel()

    ax[0].imshow(bin_img, cmap="gray")
    ax[0].set_title("Binary (Full Res)")
    ax[0].axis("off")

    ax[1].imshow(img_gray, cmap="gray")
    ax[1].imshow(chull, alpha=0.3, cmap="hot")
    ax[1].set_title("Convex Hull Overlay")
    ax[1].axis("off")

    results_for_csv = []

    for region in regions:
        if region.area >= min_area:
            minr, minc, maxr, maxc = region.bbox  # (row, col) = (y, x)

            # ----- Dessin bbox & centroïde -----
            rect = mpatches.Rectangle(
                (minc, minr), maxc - minc, maxr - minr,
                fill=False, edgecolor="red", linewidth=2
            )
            cy, cx = region.centroid
            circle = mpatches.Circle((cx, cy), 25, fill=False, edgecolor="yellow")
            ax[1].add_patch(rect)
            ax[1].add_patch(circle)

            # ----- Métriques -----
            region_label     = region.label
            region_perimeter = region.perimeter
            region_area      = region.area
            region_height    = maxr - minr          # profondeur
            region_width     = maxc - minc          # largeur
            region_y_top     = minr                 # 1ʳᵉ ligne de l’objet
            region_y_bottom  = maxr - 1             # dernière ligne de l’objet

            results_for_csv.append({
                "Label"     : filename_no_ext,
                "num_label" : region_label,
                "perimeter" : region_perimeter,
                "area"      : region_area,
                "profondeur": region_height,
                "largeur"   : region_width,
                "y_top"     : region_y_top,
                "y_bottom"  : region_y_bottom
            })

    # Figure overlay HD
    overlay_path = os.path.join(
        output_folder, f"resume_{filename_no_ext}_convex_hull2.png"
    )
    plt.tight_layout()
    plt.savefig(overlay_path, dpi=300)
    plt.close(fig)

    return results_for_csv


def main():
    print("===== Convex Hull Analysis with High-Resolution Overlay =====")

    # 1) Dossier source
    path_taskid = input("Enter folder taskid containing folder name segmended cor containing '_cor.png' images: ").strip()
    path_to_target_segmended_cor = os.path.join(path_taskid, "segmented_cor")
    if not os.path.isdir(path_to_target_segmended_cor):
        print(f"Error: {path_to_target_segmended_cor} is not a valid folder.")
        sys.exit(1)

    # 2) Dossier de sortie
    output_folder = os.path.join(path_taskid, "convex_hull")
    os.makedirs(output_folder, exist_ok=True)

    # 3) Liste des fichiers *_cor.png*
    cor_files = sorted(f for f in os.listdir(path_to_target_segmended_cor) if f.endswith("_cor.png"))
    if not cor_files:
        print(f"No files ending with '_cor.png' found in {path_to_target_segmended_cor}")
        sys.exit(0)

    print(f"Found {len(cor_files)} image(s) to process.\n")

    # 4) Traitement parallèle
    all_results = []
    with concurrent.futures.ProcessPoolExecutor(max_workers=10) as executor:
        future_to_file = {
            executor.submit(
                analyze_one_image,
                os.path.join(path_to_target_segmended_cor, f_name),
                output_folder,
                4000
            ): f_name
            for f_name in cor_files
        }

        for future in concurrent.futures.as_completed(future_to_file):
            f_name = future_to_file[future]
            try:
                all_results.extend(future.result())
            except Exception as exc:
                print(f"Error processing {f_name}: {exc}")

    # 5) CSV final
    if all_results:
        df = pd.DataFrame(
            all_results,
            columns=[
                "Label",
                "num_label",
                "perimeter",
                "area",
                "profondeur",
                "largeur",
                "y_top",
                "y_bottom"
            ]
        )
        csv_path = os.path.join(path_taskid, "result_convex_hull.csv")
        # décimales « , » si tu travailles en français ; sinon mets '.' :
        df.to_csv(csv_path, decimal=",", index=False)
        print(f"\nCSV saved to: {csv_path}")
    else:
        print("No valid regions found above the area threshold. CSV not created.")


if __name__ == "__main__":
    main()