import panel as pn
import pandas as pd
import numpy as np
from hdf5 import HDF5Reader

class DataList:
    """데이터 리스트 표시 담당 클래스 - 이미지 그리드 표시 with Pagination"""
    
    def __init__(self, reader: HDF5Reader):
        self.reader = reader
        self.current_df = None
        self.filtered_indices = None  # 현재 필터링된 인덱스 저장
        
        # Pagination 설정
        self.page_size = 100  # 한 페이지에 표시할 이미지 개수
        self.current_page = 1  # 현재 페이지 (1부터 시작)
        
        self._create_widgets()
        self._setup_callbacks()
    
    def _create_widgets(self):
        """위젯 생성"""
        # 이미지 그리드를 담을 컨테이너
        self.image_grid = pn.FlexBox(
            sizing_mode='stretch_both',
            gap='15px',
            styles={
                'padding': '10px',
                'overflow-y': 'auto',
                'overflow-x': 'hidden'
            }
        )
        
        # Pagination 컨트롤
        self.prev_button = pn.widgets.Button(
            name='◀ Previous',
            button_type='primary',
            width=100,
            disabled=True
        )
        
        self.next_button = pn.widgets.Button(
            name='Next ▶',
            button_type='primary',
            width=100,
            disabled=True
        )
        
        self.page_info = pn.pane.HTML(
            "<div style='padding:5px; font-weight:bold;'>Page 1 / 1 (0 items)</div>",
            sizing_mode='fixed',
            width=200
        )
        
        self.page_size_select = pn.widgets.Select(
            name='Items per page:',
            options=[50, 100, 200, 500],
            value=100,
            width=150
        )
    
    def _setup_callbacks(self):
        """콜백 설정"""
        self.prev_button.on_click(self._on_prev_page)
        self.next_button.on_click(self._on_next_page)
        self.page_size_select.param.watch(self._on_page_size_change, 'value')
    
    def _on_prev_page(self, event):
        """이전 페이지로 이동"""
        if self.current_page > 1:
            self.current_page -= 1
            self._refresh_grid()
    
    def _on_next_page(self, event):
        """다음 페이지로 이동"""
        total_pages = self._get_total_pages()
        if self.current_page < total_pages:
            self.current_page += 1
            self._refresh_grid()
    
    def _on_page_size_change(self, event):
        """페이지 크기 변경"""
        self.page_size = event.new
        self.current_page = 1  # 첫 페이지로 리셋
        self._refresh_grid()
    
    def _get_display_indices(self):
        """현재 표시할 인덱스 결정"""
        if self.filtered_indices is not None:
            return self.filtered_indices
        elif self.current_df is not None:
            return self.current_df.index.tolist()
        else:
            return []
    
    def _get_total_pages(self):
        """전체 페이지 수 계산"""
        display_indices = self._get_display_indices()
        total_items = len(display_indices)
        return max(1, (total_items + self.page_size - 1) // self.page_size)
    
    def _get_current_page_indices(self):
        """현재 페이지에 표시할 인덱스만 반환"""
        display_indices = self._get_display_indices()
        total_items = len(display_indices)
        
        # 페이지 범위 계산
        start_idx = (self.current_page - 1) * self.page_size
        end_idx = min(start_idx + self.page_size, total_items)
        
        return display_indices[start_idx:end_idx]
    
    def _update_pagination_controls(self):
        """Pagination 컨트롤 업데이트"""
        display_indices = self._get_display_indices()
        total_items = len(display_indices)
        total_pages = self._get_total_pages()
        
        # 버튼 활성화/비활성화
        self.prev_button.disabled = (self.current_page <= 1)
        self.next_button.disabled = (self.current_page >= total_pages)
        
        # 페이지 정보 업데이트
        start_item = (self.current_page - 1) * self.page_size + 1
        end_item = min(self.current_page * self.page_size, total_items)
        
        if total_items == 0:
            self.page_info.object = "<div style='padding:5px; font-weight:bold;'>No items</div>"
        else:
            self.page_info.object = f"<div style='padding:5px; font-weight:bold;'>Page {self.current_page} / {total_pages} (Items {start_item}-{end_item})</div>"
    
    def _get_aed_column(self):
        """AED 컬럼명 찾기"""
        if self.current_df is None:
            return None
        for col in self.current_df.columns:
            if col.upper() == 'AED':
                return col
        return None
    
    def _create_image_card(self, idx, img_html, aed_value=None):
        """개별 이미지 카드 생성 - 이미지, ID, AED 표시"""
        # 이미지에서 실제 이미지 태그만 추출
        import re
        img_match = re.search(r'<img[^>]+>', img_html)
        if img_match:
            img_tag = img_match.group(0)
        else:
            img_tag = img_html
        
        # AED 표시 문자열
        aed_str = ""
        if aed_value is not None:
            try:
                aed_str = (
                    '<div style="font-size:11px; color:#888; line-height:1.2;">'
                    f'AED: {aed_value:.2f}</div>'
                )
            except (TypeError, ValueError):
                pass
        
        # 카드 HTML 생성 (이미지 + ID + AED)
        card_html = f"""
        <div style="
            border: 1px solid #ddd;
            background: #f9f9f9;
            border-radius: 4px;
            padding: 8px;
            display: flex;
            flex-direction: column;
            align-items: center;
            width: fit-content;
        ">
            {img_tag}
            <div style="
                margin-top: 5px;
                font-size: 12px;
                font-weight: bold;
                color: #666;
                text-align: center;
                line-height: 1.2;
            ">
                #{idx}
            </div>
            {aed_str}
        </div>
        """
        
        return pn.pane.HTML(
            card_html,
            sizing_mode='fixed',
            styles={'margin': '0'}
        )
    
    def _refresh_grid(self):
        """그리드 새로고침 - 현재 페이지의 이미지만 로딩 (배치 업데이트)"""
        if self.current_df is None:
            return
        
        # 현재 페이지의 인덱스만 가져오기
        page_indices = self._get_current_page_indices()
        
        # AED 컬럼명 찾기
        aed_col = self._get_aed_column()
        
        # 이미지 카드들을 먼저 모두 생성 (렌더링 전)
        cards = []
        for idx in page_indices:
            if idx < len(self.current_df):
                img_html = self.reader.get_particle_image(idx)
                
                if img_html:
                    # AED 값 가져오기
                    aed_value = None
                    if aed_col and idx in self.current_df.index:
                        try:
                            aed_value = self.current_df.at[idx, aed_col]
                        except (KeyError, IndexError):
                            pass
                    
                    card = self._create_image_card(idx, img_html, aed_value)
                    cards.append(card)
        
        # 한 번에 그리드 업데이트 (깜빡임 방지)
        self.image_grid.objects = cards
        
        # Pagination 컨트롤 업데이트
        self._update_pagination_controls()
    
    def update_data(self, df: pd.DataFrame):
        """데이터 업데이트"""
        self.current_df = df
        self.filtered_indices = None  # 전체 데이터로 초기화
        self.current_page = 1  # 첫 페이지로 리셋
        
        self._refresh_grid()
    
    def filter_data(self, indices: list):
        """선택된 인덱스의 데이터만 표시"""
        print(f"[DataList] filter_data called with {len(indices)} indices")
        
        if self.current_df is None:
            print(f"[DataList] current_df is None, returning")
            return
        
        # 필터링된 인덱스 저장
        self.filtered_indices = indices
        self.current_page = 1  # 첫 페이지로 리셋
        
        # 빈 리스트면 빈 그리드 표시
        if len(indices) == 0:
            print(f"[DataList] Empty indices, showing empty grid")
            self.image_grid.objects = []  # 배치 업데이트로 비우기
            self._update_pagination_controls()
            return
        
        # 그리드 새로고침
        self._refresh_grid()
    
    def reset_filter(self):
        """필터 초기화 - 전체 데이터 표시"""
        if self.current_df is None:
            return
        
        # 필터링 인덱스 초기화
        self.filtered_indices = None
        self.current_page = 1  # 첫 페이지로 리셋
        
        # 그리드 새로고침
        self._refresh_grid()
    
    def get_layout(self):
        """리스트 레이아웃 반환"""
        # 헤더 행
        header_row = pn.Row(
            pn.pane.Markdown("## Particles List", margin=(5, 10, 0, 10)),
            sizing_mode='stretch_width'
        )
        
        # Pagination 컨트롤 행
        pagination_row = pn.Row(
            self.prev_button,
            self.page_info,
            self.next_button,
            pn.layout.HSpacer(),
            self.page_size_select,
            sizing_mode='stretch_width',
            align='center',
            margin=(5, 10, 5, 10)  # 여백 줄임
        )
        
        return pn.Column(
            header_row,
            pagination_row,
            self.image_grid,
            sizing_mode='stretch_both',
            margin=0  # 전체 여백 제거
        )