#!/usr/bin/env python3
"""
progress_utils.py - Progress Bar ve İndirme Hızı Göstergesi

Bu modül indirme ve yükleme işlemleri için progress bar ve hız göstergesi sağlar.
"""

import sys
import time
import threading
from typing import Optional, Callable
from urllib.request import urlopen
from urllib.error import URLError

class ProgressBar:
    """Progress bar sınıfı"""
    
    def __init__(self, total: int, description: str = "İndiriliyor", width: int = 50):
        self.total = total
        self.description = description
        self.width = width
        self.current = 0
        self.start_time = time.time()
        self.last_update = 0
        self.speed = 0
        self.lock = threading.Lock()
    
    def update(self, current: int, speed: Optional[float] = None):
        """Progress bar'ı günceller"""
        with self.lock:
            self.current = current
            if speed is not None:
                self.speed = speed
            
            # Hız hesaplama
            if self.current > 0:
                elapsed = time.time() - self.start_time
                if elapsed > 0:
                    self.speed = self.current / elapsed
    
    def display(self):
        """Progress bar'ı ekranda gösterir"""
        if self.total <= 0:
            return
        
        percentage = (self.current / self.total) * 100
        filled_width = int(self.width * self.current // self.total)
        
        # Progress bar oluştur
        bar = '█' * filled_width + '░' * (self.width - filled_width)
        
        # Hız formatı
        speed_str = self._format_speed(self.speed)
        
        # Yüzde ve boyut bilgisi
        current_str = self._format_size(self.current)
        total_str = self._format_size(self.total)
        
        # Progress bar çıktısı
        progress_line = f"\r{self.description}: [{bar}] {percentage:5.1f}% | {current_str}/{total_str} | {speed_str}"
        
        # Satırı temizle ve yaz
        sys.stdout.write('\r' + ' ' * (len(progress_line) + 10))  # Temizle
        sys.stdout.write(progress_line)
        sys.stdout.flush()
    
    def finish(self, success: bool = True):
        """Progress bar'ı tamamlar"""
        if success:
            # Tamamlandı mesajı
            sys.stdout.write('\r' + ' ' * (self.width + 50))  # Temizle
            sys.stdout.write(f"\r✅ {self.description} tamamlandı!\n")
        else:
            # Hata mesajı
            sys.stdout.write('\r' + ' ' * (self.width + 50))  # Temizle
            sys.stdout.write(f"\r❌ {self.description} başarısız!\n")
        sys.stdout.flush()
    
    def _format_speed(self, speed: float) -> str:
        """Hızı formatlar (B/s, KB/s, MB/s)"""
        if speed < 1024:
            return f"{speed:.1f} B/s"
        elif speed < 1024 * 1024:
            return f"{speed/1024:.1f} KB/s"
        else:
            return f"{speed/(1024*1024):.1f} MB/s"
    
    def _format_size(self, size: int) -> str:
        """Boyutu formatlar (B, KB, MB, GB)"""
        if size < 1024:
            return f"{size} B"
        elif size < 1024 * 1024:
            return f"{size/1024:.1f} KB"
        elif size < 1024 * 1024 * 1024:
            return f"{size/(1024*1024):.1f} MB"
        else:
            return f"{size/(1024*1024*1024):.1f} GB"


def download_with_progress(url: str, filename: str, description: str = "İndiriliyor") -> bool:
    """
    Progress bar ile dosya indirir
    
    Args:
        url: İndirilecek URL
        filename: Kaydedilecek dosya adı
        description: Progress bar açıklaması
        
    Returns:
        Başarılı ise True
    """
    try:
        # URL'den dosya boyutunu al
        response = urlopen(url)
        total_size = int(response.headers.get('content-length', 0))
        response.close()
        
        # Progress bar oluştur
        progress = ProgressBar(total_size, description)
        
        # İndirme işlemi
        with urlopen(url) as response:
            with open(filename, 'wb') as file:
                downloaded = 0
                chunk_size = 8192
                
                while True:
                    chunk = response.read(chunk_size)
                    if not chunk:
                        break
                    
                    file.write(chunk)
                    downloaded += len(chunk)
                    
                    # Progress bar güncelle
                    progress.update(downloaded)
                    progress.display()
                    
                    # Kısa bekleme (çok sık güncelleme önlemek için)
                    time.sleep(0.01)
        
        # Tamamlandı
        progress.finish(True)
        return True
        
    except Exception as e:
        if 'progress' in locals():
            progress.finish(False)
        print(f"❌ İndirme hatası: {e}")
        return False


def copy_with_progress(src: str, dst: str, description: str = "Kopyalanıyor") -> bool:
    """
    Progress bar ile dosya kopyalar
    
    Args:
        src: Kaynak dosya
        dst: Hedef dosya
        description: Progress bar açıklaması
        
    Returns:
        Başarılı ise True
    """
    import os
    import shutil
    
    try:
        # Dosya boyutunu al
        total_size = os.path.getsize(src)
        
        # Progress bar oluştur
        progress = ProgressBar(total_size, description)
        
        # Kopyalama işlemi
        with open(src, 'rb') as src_file:
            with open(dst, 'wb') as dst_file:
                copied = 0
                chunk_size = 8192
                
                while True:
                    chunk = src_file.read(chunk_size)
                    if not chunk:
                        break
                    
                    dst_file.write(chunk)
                    copied += len(chunk)
                    
                    # Progress bar güncelle
                    progress.update(copied)
                    progress.display()
                    
                    # Kısa bekleme
                    time.sleep(0.001)
        
        # Tamamlandı
        progress.finish(True)
        return True
        
    except Exception as e:
        if 'progress' in locals():
            progress.finish(False)
        print(f"❌ Kopyalama hatası: {e}")
        return False


def extract_with_progress(zip_path: str, extract_path: str, description: str = "Çıkarılıyor") -> bool:
    """
    Progress bar ile ZIP dosyası çıkarır
    
    Args:
        zip_path: ZIP dosyası yolu
        extract_path: Çıkarılacak dizin
        description: Progress bar açıklaması
        
    Returns:
        Başarılı ise True
    """
    import zipfile
    import os
    
    try:
        with zipfile.ZipFile(zip_path, 'r') as zip_ref:
            # Toplam dosya sayısı
            file_list = zip_ref.filelist
            total_files = len(file_list)
            
            if total_files == 0:
                print(f"❌ ZIP dosyası boş: {zip_path}")
                return False
            
            # Progress bar oluştur
            progress = ProgressBar(total_files, description)
            
            # Çıkarma işlemi
            for i, file_info in enumerate(file_list):
                zip_ref.extract(file_info, extract_path)
                
                # Progress bar güncelle
                progress.update(i + 1)
                progress.display()
                
                # Kısa bekleme
                time.sleep(0.01)
        
        # Tamamlandı
        progress.finish(True)
        return True
        
    except Exception as e:
        if 'progress' in locals():
            progress.finish(False)
        print(f"❌ Çıkarma hatası: {e}")
        return False


def show_success_message(message: str):
    """Başarı mesajı gösterir"""
    print(f"✅ {message}")


def show_error_message(message: str):
    """Hata mesajı gösterir"""
    print(f"❌ {message}")


def show_info_message(message: str):
    """Bilgi mesajı gösterir"""
    print(f"ℹ️  {message}")


def show_warning_message(message: str):
    """Uyarı mesajı gösterir"""
    print(f"⚠️  {message}") 