import os
import numpy as np
import cv2
from PySide6.QtCore import Qt
from pathlib import Path
from PySide6.QtGui import QDragEnterEvent, QDropEvent
from PySide6.QtWidgets import (
    QWidget,QLabel,QPushButton,
    QVBoxLayout,QHBoxLayout,
    QFileDialog, QMessageBox
)
from app_status import AppStatus
from pipeline.app_pipeline import ImagePipeline
from lib.common_widget import bgr_to_qpixmap
 

IMAGE_EXT = {".jpg", ".jpeg", ".png", ".bmp", ".gif"}
VIDEO_EXT = {".mp4", ".mov", ".avi", ".mkv", ".m4v"}

from lib.custom_logger import get_logger
logger = get_logger()

class MediaViewer(QWidget):
    """画像と動画を共通で扱う左側ビューワ"""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.status = AppStatus()

        # ボタンバー
        self.btn_bar = QHBoxLayout()
        self.btn_open = QPushButton("Open") 
        self.btn_play = QPushButton("Play")
        self.btn_pause = QPushButton("Pause")
        self.btn_stop = QPushButton("Stop")
        self.btn_clear = QPushButton("Clear")
        self.btn_analyze = QPushButton("Analyze")
        self.update_button_state()

        for b in (
            self.btn_open, self.btn_play, self.btn_pause, self.btn_stop,
            self.btn_clear, self.btn_analyze):
            self.btn_bar.addWidget(b)

        self.btn_bar.addStretch()
        self.btn_open.clicked.connect(self.open_file)



        self.label = QLabel("Drop files here\n(画像/動画)")
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setStyleSheet("background:#222;color:#aaa;border:1px solid #444;")
        self.label.setMinimumSize(640, 360)

        lay = QVBoxLayout(self)
        lay.addLayout(self.btn_bar)
        lay.addWidget(self.label, 1)

        # events
        self.btn_analyze.clicked.connect(self.on_analyze_view)


    def load(self, path: str):
        """画像または動画を読み込む"""
        self.status.current_media_path = path
        suffix = Path(path).suffix.lower()

        if suffix in IMAGE_EXT:            
            logger.info(f"Loading image: {path}")
            self.status.is_video = False
            # numpy 画像読み込み(ファイルをバイナリuint8)で読み込む
            data = np.fromfile(path, dtype=np.uint8)
            # OpenCVのデコーダに渡して画像を復元
            # (cv2.IMREAD_COLOR で3チャンネル=BGR,8bit/チャネル (uint8)
            self.status.original_image = cv2.imdecode(data, cv2.IMREAD_COLOR)
            if self.status.original_image is None:
                logger.error(f"Failed to decode image: {path}")
                # アラート表示
                QMessageBox.critical(self, "Error", f"画像を読み込めませんでした:\n{path}")
                return
            # 画像をQPixmapに変換して表示 アスペクト比を維持してリサイズ
            self.label.setPixmap(bgr_to_qpixmap(self.status.original_image).scaled(
                self.label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
            self.update_button_state()
            # 画像解析パイプラインを実行
            pipeline = ImagePipeline()
            pipeline.run()


        elif suffix in VIDEO_EXT:
            logger.info(f"Loading video: {path}")
            self.status.is_video = True
        else:
            logger.warning(f"Unsupported media type: {path}")
            self.label.setText("未対応の形式です")

    def on_analyze_view(self):
        # 画像をoverlay表示
        if self.status.overlay_image is  None:
            logger.warning("No overlay image to display")
            # アラート表示
            QMessageBox.critical(self, "Error", f"解析画像を読み込めませんでした")    
            return

        # 画像をQPixmapに変換して表示 アスペクト比を維持してリサイズ
        self.label.setPixmap(bgr_to_qpixmap(self.status.overlay_image).scaled(
                self.label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))




    def open_file(self):
        """ファイル選択ダイアログを開く"""
        path, _ = QFileDialog.getOpenFileName(self, "Open media", "", 
                                              "Media (*.jpg *.jpeg *.png *.bmp *.gif *.mp4 *.mov *.avi *.mkv *.m4v)")
        if path:
            self.load(path)

    def update_button_state(self):
        """ボタンの有効/無効を更新"""
        if not self.status.current_media_path:
            logger.debug("No media loaded, disabling buttons")
            self.btn_open.setEnabled(True)
            self.btn_play.setEnabled(False)
            self.btn_pause.setEnabled(False)
            self.btn_stop.setEnabled(False)
            self.btn_clear.setEnabled(False)
            self.btn_analyze.setEnabled(False)
            return
    
        if not self.status.is_video:
            logger.debug("image loaded, disabling video buttons")
            self.btn_open.setEnabled(True)
            self.btn_play.setEnabled(False)
            self.btn_pause.setEnabled(False)
            self.btn_stop.setEnabled(False)
            self.btn_clear.setEnabled(True)
            self.btn_analyze.setEnabled(True)




    # ---- D&D ----
    # mainwindowにも処理が必要
    def dragEnterEvent(self, e: QDragEnterEvent):
        if e.mimeData().hasUrls():
            e.acceptProposedAction()

    def dropEvent(self, e: QDropEvent):
        urls = e.mimeData().urls()
        if not urls:
            return
        path = urls[0].toLocalFile()
        if os.path.isfile(path):
            self.load(path)
