import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'dart:async';
import 'dart:io';

class PerformanceUtils {
  // Fungsi untuk menerapkan caching pada data
  static Map<String, dynamic> _cache = {};
  static Map<String, DateTime> _cacheExpiry = {};
  
  static Future<T> cachedFuture<T>({
    required String key, 
    required Future<T> Function() fetcher,
    Duration expiryDuration = const Duration(minutes: 5),
    bool forceRefresh = false,
  }) async {
    final now = DateTime.now();
    
    // Cek apakah data ada di cache dan masih valid
    if (!forceRefresh && 
        _cache.containsKey(key) && 
        _cacheExpiry.containsKey(key) &&
        now.isBefore(_cacheExpiry[key]!)) {
      return _cache[key] as T;
    }
    
    // Jika tidak ada di cache atau sudah expired, ambil data baru
    final result = await fetcher();
    _cache[key] = result;
    _cacheExpiry[key] = now.add(expiryDuration);
    
    return result;
  }
  
  // Helper untuk membersihkan cache
  static void clearCache() {
    _cache.clear();
    _cacheExpiry.clear();
  }
  
  // Helper untuk membersihkan cache tertentu
  static void clearCacheByKey(String keyPattern) {
    final keysToRemove = _cache.keys.where(
      (key) => key.contains(keyPattern)
    ).toList();
    
    for (final key in keysToRemove) {
      _cache.remove(key);
      _cacheExpiry.remove(key);
    }
  }
  
  // Image optimization di isolate terpisah
  static Future<Uint8List> optimizeImageInBackground(Uint8List imageBytes, {int maxSize = 800, int quality = 75}) async {
    return compute(_processImageInBackground, {
      'imageBytes': imageBytes,
      'maxSize': maxSize,
      'quality': quality
    });
  }
  
  // Fungsi untuk dijalankan di isolate terpisah
  static Uint8List _processImageInBackground(Map<String, dynamic> params) {
    try {
      final imageBytes = params['imageBytes'] as Uint8List;
      final maxSize = params['maxSize'] as int;
      final quality = params['quality'] as int;
      
      // Library image processing akan digunakan disini
      // Untuk contoh, kita return data asli
      return imageBytes;
      
      // Implementasi sebenarnya akan melakukan resize dan kompresi
    } catch (e) {
      print('Error processing image: $e');
      return params['imageBytes'] as Uint8List;
    }
  }
}

// Widget untuk mengurangi rebuilding child
class OptimizedBuilder extends StatefulWidget {
  final Widget Function(BuildContext) builder;
  final bool Function(BuildContext, Widget?)? shouldUpdate;
  
  const OptimizedBuilder({
    Key? key,
    required this.builder,
    this.shouldUpdate,
  }) : super(key: key);
  
  @override
  State<OptimizedBuilder> createState() => _OptimizedBuilderState();
}

class _OptimizedBuilderState extends State<OptimizedBuilder> {
  late Widget _child;
  
  @override
  void initState() {
    super.initState();
    _child = widget.builder(context);
  }
  
  @override
  void didUpdateWidget(OptimizedBuilder oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.shouldUpdate?.call(context, _child) ?? true) {
      _child = widget.builder(context);
    }
  }
  
  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
      child: _child,
    );
  }
}

// Reusable spacing widgets
class Spacing {
  // Height spacers
  static const h4 = SizedBox(height: 4);
  static const h8 = SizedBox(height: 8);
  static const h12 = SizedBox(height: 12);
  static const h16 = SizedBox(height: 16);
  static const h20 = SizedBox(height: 20);
  static const h24 = SizedBox(height: 24);
  static const h32 = SizedBox(height: 32);
  
  // Width spacers
  static const w4 = SizedBox(width: 4);
  static const w8 = SizedBox(width: 8);
  static const w12 = SizedBox(width: 12);
  static const w16 = SizedBox(width: 16);
  static const w20 = SizedBox(width: 20);
  static const w24 = SizedBox(width: 24);
  
  // Custom spacer
  static SizedBox height(double height) => SizedBox(height: height);
  static SizedBox width(double width) => SizedBox(width: width);
}

// LazyLoadingIndexedStack untuk efisiensi render tab
class LazyLoadingIndexedStack extends StatefulWidget {
  final int index;
  final List<Widget> children;
  final AlignmentGeometry alignment;
  final TextDirection? textDirection;
  final StackFit sizing;

  const LazyLoadingIndexedStack({
    Key? key,
    required this.index,
    required this.children,
    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.sizing = StackFit.loose,
  }) : super(key: key);

  @override
  _LazyLoadingIndexedStackState createState() => _LazyLoadingIndexedStackState();
}

class _LazyLoadingIndexedStackState extends State<LazyLoadingIndexedStack> {
  List<bool> _initiated = [];

  @override
  void initState() {
    super.initState();
    _initiated = List<bool>.filled(widget.children.length, false);
    _initiated[widget.index] = true;
  }

  @override
  void didUpdateWidget(LazyLoadingIndexedStack oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (_initiated.length != widget.children.length) {
      _initiated = List<bool>.filled(widget.children.length, false);
      for (int i = 0; i < oldWidget.children.length && i < _initiated.length; i++) {
        _initiated[i] = true;
      }
    }
    _initiated[widget.index] = true;
  }

  @override
  Widget build(BuildContext context) {
    return IndexedStack(
      index: widget.index,
      alignment: widget.alignment,
      textDirection: widget.textDirection,
      sizing: widget.sizing,
      children: _initiated.asMap().map((index, initiated) {
        return MapEntry(
          index, 
          initiated ? widget.children[index] : const SizedBox.shrink()
        );
      }).values.toList(),
    );
  }
}

// Memory Management Utils
class MemoryManager {
  static final Map<String, dynamic> _weakCache = {};
  static final Set<Timer> _activeTimers = {};

  // Clean up timers saat aplikasi background atau inactive
  static void cleanupTimers() {
    for (var timer in _activeTimers) {
      timer.cancel();
    }
    _activeTimers.clear();
  }

  // Mendaftar timer agar bisa di-cleanup saat perlu
  static void registerTimer(Timer timer) {
    _activeTimers.add(timer);
  }

  // Menghapus timer dari registry
  static void unregisterTimer(Timer timer) {
    _activeTimers.remove(timer);
  }

  // Cache data dengan weak references
  static void cacheData(String key, dynamic data) {
    _weakCache[key] = data;
  }

  // Dapatkan data dari cache
  static dynamic getCachedData(String key) {
    return _weakCache[key];
  }

  // Dispose images dan large objects
  static void disposeObjects(List<dynamic> objects) {
    for (var obj in objects) {
      if (obj is ImageProvider) {
        imageCache.evict(obj);
      }
    }
  }

  // Cleanup semua cache
  static void clearAll() {
    _weakCache.clear();
    cleanupTimers();
    imageCache.clear();
    imageCache.clearLiveImages();
  }
} 