package com.cube.examples;

import com.cube.storage.LSMStorageEngine;
import com.cube.storage.StorageEngine;

import java.util.*;

/**
 * Runnable examples for Cube database
 */
public class CubeExamples {
    
    public static void main(String[] args) throws Exception {
        System.out.println("=== Cube Database Examples ===\n");
        
        example1_BasicOperations();
        example2_PrefixScanning();
        example3_BatchOperations();
        example4_Statistics();
        
        System.out.println("\n=== All examples completed! ===");
    }
    
    /**
     * Example 1: Basic put, get, update, delete
     */
    public static void example1_BasicOperations() throws Exception {
        System.out.println("Example 1: Basic Operations");
        System.out.println("---------------------------");
        
        LSMStorageEngine storage = new LSMStorageEngine("/tmp/cube-example1");
        
        // Put
        storage.put("user:1", "Alice".getBytes());
        storage.put("user:2", "Bob".getBytes());
        System.out.println("✓ Stored 2 users");
        
        // Get
        String user1 = new String(storage.get("user:1"));
        System.out.println("✓ Retrieved user:1 = " + user1);
        
        // Update
        storage.put("user:1", "Alice Johnson".getBytes());
        String updated = new String(storage.get("user:1"));
        System.out.println("✓ Updated user:1 = " + updated);
        
        // Delete
        storage.delete("user:2");
        System.out.println("✓ Deleted user:2");
        
        storage.close();
        System.out.println();
    }
    
    /**
     * Example 2: Prefix scanning
     */
    public static void example2_PrefixScanning() throws Exception {
        System.out.println("Example 2: Prefix Scanning");
        System.out.println("--------------------------");
        
        LSMStorageEngine storage = new LSMStorageEngine("/tmp/cube-example2");
        
        // Store hierarchical data
        storage.put("user:1:name", "Alice".getBytes());
        storage.put("user:1:email", "alice@example.com".getBytes());
        storage.put("user:1:age", "30".getBytes());
        storage.put("user:2:name", "Bob".getBytes());
        storage.put("user:2:email", "bob@example.com".getBytes());
        storage.put("product:1:name", "Laptop".getBytes());
        
        // Scan for user:1 prefix
        System.out.println("Scanning for prefix 'user:1':");
        Iterator<Map.Entry<String, byte[]>> entries = storage.scanEntries("user:1");
        
        while (entries.hasNext()) {
            Map.Entry<String, byte[]> entry = entries.next();
            System.out.println("  " + entry.getKey() + " = " + new String(entry.getValue()));
        }
        
        storage.close();
        System.out.println();
    }
    
    /**
     * Example 3: Batch operations
     */
    public static void example3_BatchOperations() throws Exception {
        System.out.println("Example 3: Batch Operations");
        System.out.println("----------------------------");
        
        LSMStorageEngine storage = new LSMStorageEngine("/tmp/cube-example3");
        
        // Insert 1000 records
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < 1000; i++) {
            String key = "item:" + i;
            String value = "value:" + i;
            storage.put(key, value.getBytes());
        }
        
        long endTime = System.currentTimeMillis();
        System.out.println("✓ Inserted 1000 records in " + (endTime - startTime) + "ms");
        
        // Read them back
        startTime = System.currentTimeMillis();
        int count = 0;
        
        for (int i = 0; i < 1000; i++) {
            byte[] value = storage.get("item:" + i);
            if (value != null) {
                count++;
            }
        }
        
        endTime = System.currentTimeMillis();
        System.out.println("✓ Read " + count + " records in " + (endTime - startTime) + "ms");
        
        storage.close();
        System.out.println();
    }
    
    /**
     * Example 4: Storage statistics
     */
    public static void example4_Statistics() throws Exception {
        System.out.println("Example 4: Storage Statistics");
        System.out.println("------------------------------");
        
        LSMStorageEngine storage = new LSMStorageEngine("/tmp/cube-example4");
        
        // Insert data
        for (int i = 0; i < 100; i++) {
            storage.put("key:" + i, ("value:" + i).getBytes());
        }
        
        // Get stats
        StorageEngine.StorageStats stats = storage.getStats();
        
        System.out.println("Storage Statistics:");
        System.out.println("  Total Keys: " + stats.getTotalKeys());
        System.out.println("  Total Size: " + stats.getTotalSize() + " bytes");
        System.out.println("  MemTable Size: " + stats.getMemtableSize() + " bytes");
        System.out.println("  SSTable Count: " + stats.getSstableCount());
        
        // Flush to disk
        storage.flush();
        System.out.println("\nAfter flush:");
        stats = storage.getStats();
        System.out.println("  MemTable Size: " + stats.getMemtableSize() + " bytes");
        System.out.println("  SSTable Count: " + stats.getSstableCount());
        
        storage.close();
        System.out.println();
    }
}
