# PdfPngFolder Ver.20260503 Copyright ISI
import os
import sys
import time
import threading
import base64
import io
import subprocess
import fitz  # PyMuPDF
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import pystray
from PIL import Image

# 1. すべてのOSで共通して使えるホームディレクトリの取得
home_dir = os.path.expanduser("~")
watch_dir = os.path.join(home_dir, "Pictures", "pdfpngfolder")

# アイコン画像（Base64）
icon_base64 = """
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
"""

if not os.path.exists(watch_dir):
    os.makedirs(watch_dir)

class PDFConverterHandler(FileSystemEventHandler):
    def on_created(self, event):
        if not event.is_directory and event.src_path.lower().endswith(".pdf"):
            # ファイルの書き込み完了を少し待つ
            time.sleep(1.5)
            self.process_pdf(event.src_path)

    def process_pdf(self, pdf_path):
        try:
            doc = fitz.open(pdf_path)
            # 拡張子を除いたベース名を取得
            base_name, _ = os.path.splitext(pdf_path)
            
            for page_index in range(len(doc)):
                page = doc.load_page(page_index)
                # 最新のPyMuPDFに則り Matrix は大文字で記述
                pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))
                pix.save(f"{base_name}_{page_index+1}.png")
                
            doc.close()
            os.remove(pdf_path)
            print(f"変換完了: {pdf_path}")
        except Exception as e:
            print(f"Error: {e}")

def get_icon_image():
    icon_data = base64.b64decode(icon_base64)
    icon_io = io.BytesIO(icon_data)
    return Image.open(icon_io)

# 2. OSごとに「フォルダを開く」コマンドを判別分岐
def open_folder(icon=None, item=None):
    if sys.platform == 'win32':
        os.startfile(watch_dir)
    elif sys.platform == 'darwin':  # macOS
        subprocess.run(['open', watch_dir])
    else:  # Linux
        subprocess.run(['xdg-open', watch_dir])

def run_watcher():
    event_handler = PDFConverterHandler()
    observer = Observer()
    observer.schedule(event_handler, watch_dir, recursive=False)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except Exception as e:
        print(e)
    finally:
        observer.stop()
        observer.join()

# 3. SystemExitのログ出力を抑制して安全に終了する処理
def on_quit(icon, item):
    icon.stop()
    try:
        sys.exit(0)
    except SystemExit:
        pass  # ログ出力を無視してそのままプロセスを終了させます

if __name__ == "__main__":
    # 監視スレッドをバックグラウンド（デーモン）で開始
    t = threading.Thread(target=run_watcher, daemon=True)
    t.start()

    # タスクトレイ（メニューバー）のメニューを定義
    menu = pystray.Menu(
        pystray.MenuItem("フォルダを開く", open_folder, default=True),
        pystray.Menu.SEPARATOR,
        pystray.MenuItem("終了", on_quit)
    )

    # タスクトレイアイコンの起動
    icon = pystray.Icon("pdfpngfolder", get_icon_image(), "PDF変換監視中", menu=menu)
    icon.run()
