import socket
import json
import os
import sys
import logging

print("-" * 40)
print("Using Bestsockett v0.0.2b1")
print("-" * 40)
# Kütüphane versiyonunu burada da belirtebilirsin (isteğe bağlı)
__version__ = "0.0.2b1"
__author__ = "eykturkishyapimcisi on pypi"

def waitdata(port=5050, buffer=4524):
    """Basit bir sunucu başlatır ve gelen ilk veriyi döndürür."""
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('127.0.0.1', port))
    sock.listen(1)
    print(f"Waiting {port} port.")

    conn, addr = sock.accept()
    data = conn.recv(buffer).decode('utf-8')
    conn.close()

    # Eğer veri JSON ise otomatik çevir, değilse olduğu gibi döndür
    try:
        return json.loads(data)
    except:
        return data


def send_data(data, port=5050, ip='127.0.0.1'):
    """Veriyi (metin veya dict) hedefe gönderir."""
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect((ip, port))

    # Eğer veri bir sözlükse JSON'a çevir
    if isinstance(data, dict):
        data = json.dumps(data)

    client.send(str(data).encode('utf-8'))
    return "done"
def get_my_ip():
    """Bilgisayarın o anki yerel ağ IP adresini döndürür."""
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # Gerçek bir internet çıkışına bağlanıyormuş gibi yapıp yerel IP'yi öğrenir
        s.connect(('8.8.8.8', 80))
        ip = s.getsockname()[0]
    except Exception:
        ip = '127.0.0.1'
    finally:
        s.close()
    return ip




# 4. Portun Boş Olup Olmadığını Kontrol Etme
def is_port_open(port, ip='127.0.0.1'):
    """Bir portun açık olup olmadığını test eder."""
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(1)
    result = s.connect_ex((ip, port))
    s.close()
    return result == 0

# 5. Bağlantıyı Güvenli Kapatma
def force_close(sock_obj):
    """Verilen soket objesini zorla kapatır."""
    try:
        sock_obj.close()
        return True
    except:
        return False

# 6. Sunucu Banner Gösterimi
def get_latency(self):
    """Bağlantı hızını (Ping) milisaniye cinsinden döndürür. :D"""
    try:
        start_time = time.time()

        # Karşıya minik bir 'ping' paketi gönder
        self.send_data("ping_check_signal")

        # Karşıdan cevap bekle
        response = self.receive_data()

        if response == "pong_check_signal":
            end_time = time.time()
            # Saniyeyi milisaniyeye çeviriyoruz (s * 1000)
            latency = (end_time - start_time) * 1000
            return round(latency, 2)
        else:
            print("Bestsockett Error: Client needs to say pong_check_signal")
            return -1  # Yanlış cevap gelirse
    except Exception as e:
        print(f"Bestsockett Error: {e}")
        return -1

# 7. Zaman Aşımlı Bağlantı Testi (Ping gibi)
def ping_server(ip, port=5050, timeout=2):
    """Sunucuya ulaşılabiliyor mu kontrol eder."""
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    try:
        s.connect((ip, port))
        return True
    except:
        return False
    finally:
        s.close()

# 8. Host Adından IP Bulma (DNS)
def get_ip_by_name(hostname):
    """Örn: 'google.com' yazınca IP döndürür."""
    try:
        return socket.gethostbyname(hostname)
    except:
        return None

# 9. Socket Timeout Ayarlama
def set_global_timeout(sock, seconds):
    """Soketin bekleme süresini ayarlar."""
    sock.settimeout(seconds)

# 10. Basit Mesaj Alıcı (Start Server'ın devamı)
def quick_receive(conn, buffer=4000):
    """Bağlantıdan veriyi okur ve stringe çevirir."""
    data = conn.recv(buffer).decode('utf-8')
    return data

# 11. Sözlüğü JSON olarak Gönder
def send_json(data_dict, ip, port="5050"):
    """Python sözlüğünü (dict) JSON'a çevirip gönderir."""
    json_data = json.dumps(data_dict)
    send_data(json_data, ip, port) # Daha önce yazdığımız send_data'yı kullandık

# 12. Gelen Veriyi JSON Olarak Al
def receive_json(conn, buffer=4000):
    """Gelen byte verisini sözlük yapısına geri çevirir."""
    raw_data = quick_receive(conn, buffer)
    return json.loads(raw_data)

# 13. Verinin JSON Olup Olmadığını Sorgula
def is_json(data):
    """Gelen string geçerli bir JSON mı?"""
    try:
        json.loads(data)
        return True
    except:
        return False

# 14. Mesajı Dosyaya Yazdır
def save_to_file(data, filename="received_data.txt"):
    """Gelen veriyi anlık olarak bir dosyaya kaydeder."""
    with open(filename, "a", encoding="utf-8") as f:
        f.write(data + "\n")

# 15. JSON Ayar Dosyası Oluştur (OOP yerine Ayar Yönetimi)
def create_config(ip, port, filename="config.json"):
    """Bağlantı ayarlarını JSON dosyasına kaydeder."""
    config = {"ip": ip, "port": port}
    with open(filename, "w") as f:
        json.dump(config, f)

# 16. JSON Ayar Dosyasını Oku
def load_config(filename="config.json"):
    """Ayarları dosyadan geri okur."""
    if os.path.exists(filename):
        with open(filename, "r") as f:
            return json.load(f)
    return None

# 17. Basit Metin Şifreleme (Sezar Kaydırma gibi)
def basic_encrypt(text, key=3):
    """Mesajı ağda okunmasın diye basitçe kaydırır."""
    return "".join(chr(ord(c) + key) for c in text)

# 18. Şifre Çözücü
def basic_decrypt(text, key=3):
    """Şifreli mesajı eski haline getirir."""
    return "".join(chr(ord(c) - key) for c in text)

# 19. Büyük Veriyi Parçalara Böl (Chunking)
def split_data(data, chunk_size=1024):
    """Veriyi gönderilmeden önce küçük parçalara ayırır."""
    return [data[i:i+chunk_size] for i in range(0, len(data), chunk_size)]

# 20. Dosya Boyutu Kontrolü
def get_file_size(filepath):
    """Gönderilecek dosyanın kaç byte olduğunu söyler."""
    return os.path.getsize(filepath)

import zlib
import base64

# 31. Veriyi Sıkıştır (Compress)
def compress_data(data):
    """Veriyi zlib ile sıkıştırır ve base64 formatına çevirir."""
    if isinstance(data, str):
        data = data.encode('utf-8')
    compressed = zlib.compress(data)
    # Ağda sorun çıkmaması için base64 ile metne çeviriyoruz
    return base64.b64encode(compressed).decode('utf-8')

# 32. Sıkıştırılmış Veriyi Aç (Decompress)
def decompress_data(compressed_string):
    """Sıkıştırılmış base64 veriyi orijinal haline geri döndürür."""
    decoded = base64.b64decode(compressed_string)
    decompressed = zlib.decompress(decoded)
    return decompressed.decode('utf-8')

# 33. Sıkıştırılmış JSON Gönder
def send_compressed_json(data_dict, ip, port="5050"):
    """Sözlüğü JSON yapıp sıkıştırarak gönderir. (Tam bir hız canavarı! :D)"""
    json_data = json.dumps(data_dict)
    compressed = compress_data(json_data)
    send_data(compressed, ip, port)

# 34. Sıkıştırılmış JSON Al
def receive_compressed_json(conn, buffer=8000):
    """Gelen sıkıştırılmış veriyi açar ve JSON (dict) olarak döndürür."""
    raw_data = quick_receive(conn, buffer)
    decompressed = decompress_data(raw_data)
    return json.loads(decompressed)

# 35. Sıkıştırma Oranı Hesapla
def get_compression_ratio(original, compressed):
    """Verinin yüzde kaç küçüldüğünü hesaplar."""
    original_size = len(original)
    compressed_size = len(compressed)
    ratio = (1 - (compressed_size / original_size)) * 100
    return f"%{ratio:.2f} kazanç sağlandı! :D"

# 36. Basit Hız Testi (Ping Süresi)
import time
def get_ping_ms(ip, port=5050):
    """Sunucuya bir paket atıp kaç milisaniyede döndüğünü ölçer."""
    start = time.time()
    if ping_server(ip, port):
        return f"{(time.time() - start) * 1000:.2f} ms"
    return "Ulaşılamadı"

# 37. Yerel Ağ Tarayıcısı (Port Scanner)
def scan_ports(ip, start_port, end_port):
    """Belirli bir aralıktaki açık portları bulur."""
    open_ports = []
    for port in range(start_port, end_port + 1):
        if is_port_open(port, ip):
            open_ports.append(port)
    return open_ports


# 39. Otomatik Port Seçici
def find_free_port(start=5000):
    """Boş olan ilk portu bulur ve döndürür."""
    port = start
    while is_port_open(port):
        port += 1
    return port

# 40. Mesaj Zaman Damgası (Timestamp)
def add_timestamp(message):
    """Mesajın başına o anki saati ekler."""
    current_time = time.strftime("%H:%M:%S")
    return f"[{current_time}] {message}"



# 41. Log Dosyası Başlatıcı
def init_logger(filename="easysocket.log"):
    """Tüm ağ hareketlerini bir dosyaya kaydetmeye başlar."""
    logging.basicConfig(filename=filename, level=logging.INFO,
                        format='%(asctime)s - %(message)s')

# 42. Güvenli Gönderim (Hata Yakalamalı)
def safe_send(data, ip, port):
    """Bağlantı kopsa bile programın çökmesini engeller."""
    try:
        send_data(data, ip, port)
        return True
    except Exception as e:
        print(f"Critical Error: {e} :(")
        return False

# 43. IP Adresi Doğrulayıcı
def is_valid_ip(ip):
    """Girilen IP adresi format olarak doğru mu kontrol eder."""
    parts = ip.split(".")
    if len(parts) != 4: return False
    try:
        return all(0 <= int(part) <= 255 for part in parts)
    except:
        return False

# 44. Python Versiyon Kontrolü
def check_python_version():
    """Kütüphanenin çalışması için gereken minimum sürümü denetler."""
    if sys.version_info < (3, 6):
        print("Warning: Please use python 3.7 or newer versions.")
        return False
    return True


# 46. Bağlantı Bilgisi Yazdırıcı (Debug Mode)
def debug_connection(conn):
    """Bağlı olan istemcinin tüm teknik detaylarını ekrana basar."""
    info = conn.getpeername()
    print(f"DEBUG: Connected ip: {info[0]}, Port: {info[1]}")

# 47. Veri Tipi Kontrolü
def get_data_type(data):
    """Gelen verinin JSON mı, Metin mi olduğunu söyler."""
    if isinstance(data, dict): return "JSON/Sözlük"
    if is_json(data): return "JSON/String"
    return "Düz Metin"

# 48. Otomatik Buffer Hesaplayıcı
def suggest_buffer(data_size):
    """Veri boyutuna göre ideal buffer (tampon) boyutunu önerir."""
    if data_size < 1024: return 1024
    if data_size < 8192: return 8192
    return 16384

# 49. Kütüphane Bilgisi (About)
def about():
    """Kütüphane hakkındaki bilgileri ve sloganı yazdırır."""
    print("easysocket - This is a lib that makes socket easy to coding.")


# 50. Basit Kapatma Komutu
def kill_process():
    """Kütüphaneyi ve bağlı işlemleri tamamen durdurur."""
    print("Goodbye :(")
    sys.exit()

    # 51. Çoklu Bağlantı Dinleyici (Multi-Connection)


    # 52. Gelen Mesaja Otomatik Yanıt (Auto-Responder)
def auto_reply(conn, expected_msg, reply_msg):
        """Belirli bir kelime gelirse otomatik cevap döner."""
        data = quick_receive(conn)
        if data == expected_msg:
            conn.send(reply_msg.encode('utf-8'))
            return True
        return False

    # 53. Sunucu Durum Raporu (Server Health)
def get_server_stats(sock):
        """Sunucunun bağlı olduğu IP, Port ve protokol bilgilerini verir."""
        return {
            "address": sock.getsockname()[0],
            "port": sock.getsockname()[1],
            "family": "IPv4" if sock.family == 2 else "Diğer"
        }

    # 54. Gelen Veri Filtresi (Whitelisting)
def is_trusted_client(addr, trusted_ips):
        """Sadece listedeki IP'lerin bağlanmasına izin verir."""
        return addr[0] in trusted_ips

    # 55. Sunucu "Heartbeat" (Yaşam Sinyali)
def send_heartbeat(conn):
        """Bağlantının hala kopmadığını anlamak için minik bir 'ping' atar."""
        try:
            conn.send(b"HEARTBEAT")
            return True
        except:
            return False

    # 56. Gelen Veriyi Kategorize Et (JSON vs String)
def auto_parse_server(conn):
        """Veriyi alır; JSON ise dict, değilse string olarak döndürür."""
        raw = quick_receive(conn)
        try:
            return json.loads(raw), "JSON"
        except:
            return raw, "TEXT"

    # 57. Sunucu Log Temizleyici
def clear_server_logs(filename="easysocket.log"):
        """Sunucu şişmesin diye log dosyasını sıfırlar."""
        with open(filename, "w") as f:
            f.write("")
