import re
import tkinter as tk
from tkinter import filedialog, messagebox
import PyPDF2
import matplotlib.pyplot as plt
from wordcloud import WordCloud
import threading
import os
import sys
from konlpy.tag import Okt
from collections import Counter
import platform
sys.path.append(r'C:\ProgramData\anaconda3\Lib\site-packages')
import pyhwp

class WordCloudGenerator:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("WordCloud Generator")
        
        try:
            self.okt = Okt()
        except Exception as e:
            messagebox.showerror("초기화 오류", f"형태소 분석기 초기화 실패: {str(e)}\nKoNLPy가 설치되어 있는지 확인해주세요.")
            self.root.quit()
            sys.exit(1)
            
        self.setup_stopwords()
        self.setup_font()
        self.setup_gui()

    def setup_font(self):
        system = platform.system()
        
        if system == 'Windows':
            self.font_path = 'C:/Windows/Fonts/malgun.ttf'  
            if not os.path.exists(self.font_path):
                self.font_path = 'C:/Windows/Fonts/gulim.ttc'  
        elif system == 'Darwin':
            self.font_path = '/System/Library/Fonts/AppleSDGothicNeo.ttc'
        else:
            self.font_path = '/usr/share/fonts/truetype/nanum/NanumGothic.ttf'
            
        if not os.path.exists(self.font_path):
            messagebox.showwarning("폰트 경고", 
                                 "기본 한글 폰트를 찾을 수 없습니다.\n"
                                 "워드클라우드 생성 시 한글이 제대로 표시되지 않을 수 있습니다.")
            self.font_path = None

    def setup_stopwords(self):
        self.korean_stop_words = {
            '있', '하', '것', '들', '그', '되', '수', '이', '보', '않', '없', '나',
            '사람', '주', '아니', '등', '같', '우리', '때', '년', '가', '한', '지',
            '대하', '오', '말', '일', '그렇', '위하', '때문', '그것', '두', '말하',
            '알', '그러나', '받', '못하', '일', '그런', '또', '문제', '더', '사회',
            '많', '그리고', '좋', '크', '따르', '중', '나오', '가지', '씨', '시키',
            '만들', '지금', '생각하', '그러', '속', '하나', '집', '살', '모르',
            '적', '월', '데', '자신', '안', '어떤', '내', '경우', '명', '생각',
            '시간', '그녀', '다시', '이런', '앞', '보이', '번', '나', '다른',
            '어떻', '여자', '개', '전', '들', '사실', '이렇', '점', '싶', '말',
            '정도', '좀', '원', '잘', '통하', '소리', '놓'
        }

        self.english_stop_words = {
            'i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you',
            "you're", "you've", "you'll", "you'd", 'your', 'yours', 'yourself',
            'yourselves', 'he', 'him', 'his', 'himself', 'she', "she's", 'her',
            'hers', 'herself', 'it', "it's", 'its', 'itself', 'they', 'them',
            'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom',
            'this', 'that', "that'll", 'these', 'those', 'am', 'is', 'are',
            'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having',
            'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if',
            'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for',
            'with', 'about', 'against', 'between', 'into', 'through', 'during',
            'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down',
            'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further',
            'then', 'once'
        }

    def setup_gui(self):
        """GUI 요소를 설정합니다."""
        self.frame = tk.Frame(self.root)
        self.frame.pack(padx=60, pady=25)

        self.status_label = tk.Label(self.frame, text="파일을 선택해주세요")
        self.status_label.pack(pady=5)

        self.length_frame = tk.Frame(self.frame)
        self.length_frame.pack(pady=5)
        tk.Label(self.length_frame, text="최소 글자 수:").pack(side=tk.LEFT)
        self.min_length_var = tk.StringVar(value="2")
        self.min_length_entry = tk.Entry(self.length_frame, textvariable=self.min_length_var, width=5)
        self.min_length_entry.pack(side=tk.LEFT, padx=5)

        self.max_words_frame = tk.Frame(self.frame)
        self.max_words_frame.pack(pady=5)
        tk.Label(self.max_words_frame, text="최대 단어 수:").pack(side=tk.LEFT)
        self.max_words_var = tk.StringVar(value="50")
        self.max_words_entry = tk.Entry(self.max_words_frame, textvariable=self.max_words_var, width=5)
        self.max_words_entry.pack(side=tk.LEFT, padx=5)

        self.load_button = tk.Button(
            self.frame, 
            text="PDF, 텍스트, HWP파일 불러오기", 
            command=self.process_file_async
        )
        self.load_button.pack(pady=10)

    def extract_text_from_pdf(self, pdf_path):
        text = ""
        try:
            with open(pdf_path, 'rb') as file:
                reader = PyPDF2.PdfReader(file)
                for page in reader.pages:
                    text += page.extract_text() or ""  # None 방지
        except Exception as e:
            raise Exception(f"PDF 파일 읽기 오류: {str(e)}")
        return text

    def extract_text_from_txt(self, txt_path):
        encodings = ['utf-8', 'cp949', 'euc-kr']
        for encoding in encodings:
            try:
                with open(txt_path, 'r', encoding=encoding) as file:
                    return file.read()
            except UnicodeDecodeError:
                continue
        raise Exception("텍스트 파일의 인코딩을 확인할 수 없습니다.")

    def extract_text_from_hwp(self, hwp_path):
        """HWP 파일에서 텍스트를 추출합니다."""
        try:
            # pyhwp를 사용하여 HWP 파일에서 텍스트를 추출합니다.
            doc = pyhwp.HWPDocument(hwp_path)
            text = ""
            for section in doc.bodytext:
                text += section.text.replace('\r\n', '\n') + '\n'
            return text.strip()
        except Exception as e:
            raise Exception(f"HWP 파일 읽기 오류: {str(e)}")

    def process_text(self, text):
        try:
            min_length = max(2, int(self.min_length_var.get()))
            nouns = self.okt.nouns(text)
            words = [word for word in nouns if len(word) >= min_length and word not in self.korean_stop_words]

            english_words = re.findall(r'\b[a-zA-Z]+\b', text)
            words.extend([word.lower() for word in english_words if len(word) >= min_length and word.lower() not in self.english_stop_words])

            word_freq = Counter(words)
            return dict(word_freq)
        except Exception as e:
            raise Exception(f"텍스트 처리 중 오류 발생: {str(e)}")

    def generate_wordcloud(self, word_freq):
        max_words = 50
        try:
            max_words = max(1, int(self.max_words_var.get()))
            if not word_freq:
                raise Exception("처리할 텍스트가 충분하지 않습니다.")

            wordcloud = WordCloud(
                font_path=self.font_path,
                width=1200,
                height=800,
                background_color='white',
                max_words=max_words,
                min_font_size=10,
                max_font_size=150,
                random_state=42
            ).generate_from_frequencies(word_freq)

            self.root.after(0, self.show_wordcloud, wordcloud)
        except Exception as e:
            raise Exception(f"워드클라우드 생성 중 오류 발생: {str(e)}")

    def show_wordcloud(self, wordcloud):
        plt.figure(figsize=(15, 10))
        plt.imshow(wordcloud, interpolation='bilinear')
        plt.axis('off')
        plt.show()

    def process_file_async(self):
        """파일 처리를 비동기적으로 실행합니다."""
        file_path = filedialog.askopenfilename(
            filetypes=[
                ("지원되는 파일", "*.pdf;*.txt;*.hwp"),
                ("PDF 파일", "*.pdf"),
                ("텍스트 파일", "*.txt"),
                ("HWP 파일", "*.hwp"),
            ]
        )
        
        if not file_path:
            return

        self.status_label.config(text="파일 처리 중...")
        self.load_button.config(state=tk.DISABLED)

        def process():
            try:
                if file_path.lower().endswith('.pdf'):
                    text = self.extract_text_from_pdf(file_path)
                elif file_path.lower().endswith('.txt'):
                    text = self.extract_text_from_txt(file_path)
                elif file_path.lower().endswith('.hwp'):
                    text = self.extract_text_from_hwp(file_path)
                else:
                    raise Exception("지원하지 않는 파일 형식입니다.")

                word_freq = self.process_text(text)
                self.generate_wordcloud(word_freq)

                self.status_label.config(text="처리 완료")
            except Exception as e:
                messagebox.showerror("오류", str(e))
                self.status_label.config(text="오류 발생")
            finally:
                self.load_button.config(state=tk.NORMAL)

        threading.Thread(target=process, daemon=True).start()

    def run(self):
        self.root.mainloop()

if __name__ == "__main__":
    app = WordCloudGenerator()
    app.run() 해당 코드 실행시 pyhwp를 불러오지 못하는 오류가 발생하고 있습니다. 해결 방법을 제시해주세요