# import array
import threading
import ctypes
from typing import Any, Optional, Tuple

class RingBuffer:
    """
    高效能無鎖環形緩衝區，使用原子操作避免鎖定
    用於在不同執行緒間高效傳遞資料
    """
    # 緩衝區計數器，用於自動分配 buffer_id
    _buffer_counter = 0
    _counter_lock = threading.Lock()
    
    def __init__(self, capacity: int = 256, buffer_id: int = None):
        """
        初始化環形緩衝區
        
        Args:
            capacity: 緩衝區容量 (必須是 2 的次方)
            buffer_id: 緩衝區 ID，如果為 None 則自動分配
        """
        # 確保容量是 2 的次方，便於使用位運算取模
        if capacity & (capacity - 1) != 0:
            # 找到大於等於 capacity 的最小 2 的次方
            capacity = 1 << (capacity - 1).bit_length()
        
        # 分配緩衝區 ID
        if buffer_id is None:
            with RingBuffer._counter_lock:
                buffer_id = RingBuffer._buffer_counter
                RingBuffer._buffer_counter += 1
                
        self.buffer_id = buffer_id
        self.capacity = capacity
        self.mask = capacity - 1  # 用於快速取模
        self.buffer = [None] * capacity
        
        # 原子計數器作為讀寫指標
        self.write_index = ctypes.c_uint64(0)
        self.read_index = ctypes.c_uint64(0)
        
        # 用於檢測上次操作的執行緒 ID
        self._last_read_thread = None
        self._last_write_thread = None
        
        # 添加同時讀寫統計
        self.concurrent_write_count = ctypes.c_uint64(0)  # 同時寫入計數
        self.concurrent_read_count = ctypes.c_uint64(0)   # 同時讀取計數
        self.total_write_count = ctypes.c_uint64(0)       # 總寫入操作計數
        self.total_read_count = ctypes.c_uint64(0)        # 總讀取操作計數
        self.overflow_count = ctypes.c_uint64(0)          # 緩衝區溢出次數
        
        # 記錄各執行緒的操作次數
        self.thread_write_counts = {}  # {thread_id: count}
        self.thread_read_counts = {}   # {thread_id: count}
        
        # 用於保護統計數據的鎖（僅用於統計，不影響主要讀寫操作）
        self._stats_lock = threading.Lock()
        
    def put(self, item: Any) -> bool:
        """
        將項目存入緩衝區
        
        Args:
            item: 要存入的項目
        
        Returns:
            bool: 成功寫入返回 True，緩衝區已滿返回 False
        """
        # 更新寫入統計
        self.total_write_count.value += 1
        
        # 檢測上次寫入的執行緒
        current_thread = threading.get_ident()
        
        # 記錄當前執行緒寫入次數
        with self._stats_lock:
            self.thread_write_counts[current_thread] = self.thread_write_counts.get(current_thread, 0) + 1
        
        # 檢測是否為不同執行緒同時寫入
        if self._last_write_thread is not None and current_thread != self._last_write_thread:
            self.concurrent_write_count.value += 1
        
        self._last_write_thread = current_thread
        
        # 原子獲取當前寫入位置
        current = self.write_index.value
        next_pos = (current + 1) & self.mask
        
        # 檢查緩衝區是否已滿
        if next_pos == self.read_index.value:
            self.overflow_count.value += 1
            return False
        
        # 寫入資料並原子更新寫入位置
        self.buffer[current] = item
        self.write_index.value = next_pos
        return True
    
    def get(self) -> Optional[Any]:
        """
        從緩衝區讀取項目
        
        Returns:
            項目或 None（如果緩衝區為空）
        """
        # 更新讀取統計
        self.total_read_count.value += 1
        
        # 檢測上次讀取的執行緒
        current_thread = threading.get_ident()
        
        # 記錄當前執行緒讀取次數
        with self._stats_lock:
            self.thread_read_counts[current_thread] = self.thread_read_counts.get(current_thread, 0) + 1
        
        # 檢測是否為不同執行緒同時讀取
        if self._last_read_thread is not None and current_thread != self._last_read_thread:
            self.concurrent_read_count.value += 1
        
        self._last_read_thread = current_thread
        
        # 檢查緩衝區是否為空
        if self.read_index.value == self.write_index.value:
            return None
        
        # 原子獲取當前讀取位置並讀取資料
        current = self.read_index.value
        item = self.buffer[current]
        
        # 原子更新讀取位置
        self.read_index.value = (current + 1) & self.mask
        return item
    
    def get_all(self) -> list:
        """
        獲取緩衝區中的所有項目
        
        Returns:
            list: 所有可用項目的列表
        """
        items = []
        while True:
            item = self.get()
            if item is None:
                break
            items.append(item)
        return items
    
    def size(self) -> int:
        # 返回目前緩衝區內項目數量
        return (self.write_index.value - self.read_index.value) & self.mask
    
    def is_empty(self) -> bool:
        # 檢查緩衝區是否為空
        return self.read_index.value == self.write_index.value
    
    def is_full(self) -> bool:
        # 檢查緩衝區是否已滿
        return ((self.write_index.value + 1) & self.mask) == self.read_index.value
    
    def clear(self) -> None:
        """清空緩衝區"""
        self.read_index.value = self.write_index.value
        
    def get_stats(self) -> dict:
        """
        獲取緩衝區統計資訊
        
        Returns:
            dict: 包含各種統計數據的字典
        """
        with self._stats_lock:
            stats = {
                "buffer_id": self.buffer_id,
                "capacity": self.capacity,
                "current_size": self.size(),
                "is_full": self.is_full(),
                "is_empty": self.is_empty(),
                "total_writes": self.total_write_count.value,
                "total_reads": self.total_read_count.value,
                "concurrent_writes": self.concurrent_write_count.value,
                "concurrent_reads": self.concurrent_read_count.value,
                "overflow_count": self.overflow_count.value,
                "write_threads": len(self.thread_write_counts),
                "read_threads": len(self.thread_read_counts),
                "concurrent_write_ratio": self.concurrent_write_count.value / max(1, self.total_write_count.value),
                "concurrent_read_ratio": self.concurrent_read_count.value / max(1, self.total_read_count.value),
                "top_writer_threads": sorted(self.thread_write_counts.items(), key=lambda x: x[1], reverse=True)[:3],
                "top_reader_threads": sorted(self.thread_read_counts.items(), key=lambda x: x[1], reverse=True)[:3],
            }
            return stats
    
    def print_stats(self) -> None:
        """輸出當前緩衝區統計資訊"""
        stats = self.get_stats()
        
        print(f"\n=== RingBuffer #{stats['buffer_id']} Statistics ===")
        print(f"Capacity: {stats['capacity']}, Current Size: {stats['current_size']}")
        print(f"Total Write Operations: {stats['total_writes']}")
        print(f"Total Read Operations: {stats['total_reads']}")
        print(f"Concurrent Write Events: {stats['concurrent_writes']} ({stats['concurrent_write_ratio']:.2%})")
        print(f"Concurrent Read Events: {stats['concurrent_reads']} ({stats['concurrent_read_ratio']:.2%})")
        print(f"Buffer Overflow Count: {stats['overflow_count']}")
        print(f"Writing Threads: {stats['write_threads']}")
        print(f"Reading Threads: {stats['read_threads']}")
        
        print("Top Writer Threads:")
        for thread_id, count in stats['top_writer_threads']:
            print(f"  Thread {thread_id}: {count} writes")
            
        print("Top Reader Threads:")
        for thread_id, count in stats['top_reader_threads']:
            print(f"  Thread {thread_id}: {count} reads")
        print("=============================\n")
    
    def reset_stats(self) -> None:
        """重置所有統計數據"""
        with self._stats_lock:
            self.concurrent_write_count.value = 0
            self.concurrent_read_count.value = 0
            self.total_write_count.value = 0
            self.total_read_count.value = 0
            self.overflow_count.value = 0
            self.thread_write_counts.clear()
            self.thread_read_counts.clear()
            
    def __str__(self) -> str:
        """返回緩衝區的字符串表示"""
        return f"RingBuffer(id={self.buffer_id}, capacity={self.capacity}, size={self.size()})"