import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared/utils/screen_util.dart';
import 'package:shared/utils/util.dart';

/*
   对象的扩展方法,模仿高阶函数
 */
extension LetRunApply<T> on T {
  /// let 函数与之前的示例相同,它接受一个闭包并返回其结果。
  R let<R>(R Function(T) block) {
    return block(this);
  }

  /// run 函数也与之前的示例相同,它接受一个闭包但不返回任何内容。
  void run(void Function(T) block) {
    block(this);
  }

  /// apply 函数它接受一个闭包并在当前对象上执行该闭包。然后,它返回当前对象本身
  T apply(void Function(T) block) {
    block(this);
    return this;
  }
}

/*
   String的扩展方法,用于处理占位符
 */
extension StringExtension on String {
  // 自己的校验空
  bool get checkEmpty {
    return Utils.isEmpty(this);
  }

  // 自己的校验非空
  bool get checkNotEmpty {
    return Utils.isNotEmpty(this);
  }

  // 只有一个 %s 的占位符,直接写就行
  String replacePlaceholder(String replacement) {
    String result = this;
    result = result.replaceFirst('%s', replacement);
    return result;
  }

  // 多个 %s 的占位符,使用List按顺序指定
  String replacePlaceholderList(List<String> replacements) {
    String result = this;
    for (int i = 0; i < replacements.length; i++) {
      result = result.replaceFirst('%s', replacements[i]);
    }
    return result;
  }

  // 自定义的多个占位符 ,自己写对应关系
  String replacePlaceholderMap(Map<String, String> replacements) {
    String result = this;
    replacements.forEach((key, value) {
      final pattern = RegExp(key);
      result = result.replaceAll(pattern, value);
    });
    return result;
  }

  //时间戳从毫秒转换为秒 13位数转换为10位数
  String get formartUnixTimeStamp {
    return substring(0, length - 3);
  }
}

/*
   double的扩展方法,用于ScreenUtil的扩展,主要用于容器与图片的屏幕适配
 */
extension DoubleExtension on double {
  double get ap {
    return ScreenUtil.getInstance().getAdapterSize(this);
  }
}

extension IntExtension on int {
  double get ap {
    return ScreenUtil.getInstance().getAdapterSize(toDouble());
  }
}

/*
   ViewModel中的扩展方法,用于处理网络错误
 */
extension ControllerExtension on AutoDisposeNotifier {
  /// 处理Form表单的Input错误展示(专用 的我们的Api返回错误逻辑)
  void handleFormError(Map<String, dynamic>? json, String key, void Function(String errorStr)? callback) {
    if (json?.containsKey(key) == true) {
      String errorStrs = json![key]
          .map((value) {
            if (value is String) {
              return value;
            } else {
              return '';
            }
          })
          .toList()
          .join('\r\n');

      if (!Utils.isEmpty(errorStrs)) {
        callback?.call(errorStrs);
      }
    }
  }
}

// 扩展Function,添加防抖功能
extension DebounceExtension on Function {
  void Function() debounce([int milliseconds = 500]) {
    Timer? _debounceTimer;
    return () {
      if (_debounceTimer?.isActive ?? false) _debounceTimer?.cancel();
      _debounceTimer = Timer(Duration(milliseconds: milliseconds), () {
        this(); //后执行
      });
    };
  }
}

// 扩展Function,添加节流功能
extension ThrottleExtension on Function {
  void Function() throttle([int milliseconds = 500]) {
    bool _isAllowed = true;
    Timer? _throttleTimer;
    return () {
      if (!_isAllowed) return;
      _isAllowed = false;
      this(); //先执行
      _throttleTimer?.cancel();
      _throttleTimer = Timer(Duration(milliseconds: milliseconds), () {
        _isAllowed = true;
      });
    };
  }
}

//页面中可能要用到的扩展
extension BuildContextExtensions on BuildContext {
  ThemeData get theme => Theme.of(this);

  Size get screenSize => MediaQuery.sizeOf(this);

  EdgeInsets get screenPadding => MediaQuery.paddingOf(this);

  TextScaler get screenTextScaleFactor => MediaQuery.textScalerOf(this);

  bool get isSmallScreen => screenSize.width < 800;

  bool get isMediumScreen => screenSize.width >= 800 && screenSize.width <= 1200;

  bool get isLargeScreen => screenSize.width > 800 && !isMediumScreen;

  bool get isPlatformDarkThemed => MediaQuery.platformBrightnessOf(this) == Brightness.dark;

  void showSnackBar(SnackBar snackBar) {
    ScaffoldMessenger.of(this).showSnackBar(snackBar);
  }

  void showSnackBarUsingText(String text) {
    final snackBar = SnackBar(
      content: Text(
        text,
        style: const TextStyle(color: Colors.white),
      ),
    );
    ScaffoldMessenger.of(this).showSnackBar(snackBar);
  }
}