library;

import 'package:flutter/material.dart';
import 'breakpoints.dart';

class ResponsiveSize {
  ResponsiveSize._();

  static double widthPercent(BuildContext context, double percent) {
    assert(percent >= 0 && percent <= 100, 'Percent must be between 0-100');
    return MediaQuery.of(context).size.width * (percent / 100);
  }

  static double heightPercent(BuildContext context, double percent) {
    assert(percent >= 0 && percent <= 100, 'Percent must be between 0-100');
    return MediaQuery.of(context).size.height * (percent / 100);
  }

  static double fontSize(BuildContext context, double baseSize) {
    final double scale = Breakpoints.getFontScale(context);
    final double screenWidth = MediaQuery.of(context).size.width;

    double widthScale = 1.0;
    if (screenWidth < 360) {
      widthScale = 0.9;
    } else if (screenWidth > 1920) {
      widthScale = 1.1;
    }

    return baseSize * scale * widthScale;
  }

  static double getMinTapSize(BuildContext context) {
    final TargetPlatform platform = Theme.of(context).platform;

    switch (platform) {
      case TargetPlatform.iOS:
      case TargetPlatform.android:
        return 48.0;
      case TargetPlatform.macOS:
      case TargetPlatform.windows:
      case TargetPlatform.linux:
        return 36.0;
      default:
        return 44.0;
    }
  }

  static double iconSize(BuildContext context, {double baseSize = 24}) {
    return Breakpoints.adaptive<double>(
      context: context,
      mobile: baseSize,
      tablet: baseSize * 1.2,
      desktop: baseSize,
    );
  }

  static EdgeInsets buttonPadding(BuildContext context) {
    return Breakpoints.adaptive<EdgeInsets>(
      context: context,
      mobile: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
      tablet: const EdgeInsets.symmetric(horizontal: 20, vertical: 14),
      desktop: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
    );
  }

  static double dialogWidth(BuildContext context) {
    final double screenWidth = MediaQuery.of(context).size.width;

    return Breakpoints.adaptive<double>(
      context: context,
      mobile: screenWidth * 0.9,
      tablet: screenWidth * 0.7,
      desktop: 500,
    );
  }

  static double dialogMaxHeight(BuildContext context) {
    final double screenHeight = MediaQuery.of(context).size.height;

    return Breakpoints.adaptive<double>(
      context: context,
      mobile: screenHeight * 0.8,
      tablet: screenHeight * 0.75,
      desktop: 720,
    );
  }
}

class ResponsiveSpacing {
  ResponsiveSpacing._();

  static double xs(BuildContext context) {
    return Breakpoints.adaptive<double>(
      context: context,
      mobile: 4,
      tablet: 6,
      desktop: 8,
    );
  }

  static double sm(BuildContext context) {
    return Breakpoints.adaptive<double>(
      context: context,
      mobile: 8,
      tablet: 10,
      desktop: 12,
    );
  }

  static double md(BuildContext context) {
    return Breakpoints.adaptive<double>(
      context: context,
      mobile: 16,
      tablet: 20,
      desktop: 24,
    );
  }

  static double lg(BuildContext context) {
    return Breakpoints.adaptive<double>(
      context: context,
      mobile: 24,
      tablet: 32,
      desktop: 40,
    );
  }

  static double xl(BuildContext context) {
    return Breakpoints.adaptive<double>(
      context: context,
      mobile: 32,
      tablet: 48,
      desktop: 64,
    );
  }

  static Widget verticalGap(BuildContext context, {double? size}) {
    return SizedBox(height: size ?? md(context));
  }

  static Widget horizontalGap(BuildContext context, {double? size}) {
    return SizedBox(width: size ?? md(context));
  }
}

class ResponsiveLayout {
  ResponsiveLayout._();

  static int formColumns(BuildContext context) {
    return Breakpoints.adaptive<int>(
      context: context,
      mobile: 1,
      tablet: 2,
      desktop: 2,
    );
  }

  static int gridCrossAxisCount(BuildContext context, {int? maxColumns}) {
    final int columns = Breakpoints.getGridColumns(context);
    return maxColumns != null ? columns.clamp(1, maxColumns) : columns;
  }

  static double gridAspectRatio(BuildContext context) {
    return Breakpoints.adaptive<double>(
      context: context,
      mobile: 1.0,
      tablet: 1.2,
      desktop: 1.5,
    );
  }

  static bool useSingleColumn(BuildContext context) {
    return Breakpoints.isMobile(context);
  }

  static bool useDualPane(BuildContext context) {
    return Breakpoints.isTabletOrLarger(context);
  }

  static int getFlex(BuildContext context, {
    int mobileFlex = 1,
    int? tabletFlex,
    int? desktopFlex,
  }) {
    return Breakpoints.adaptive<int>(
      context: context,
      mobile: mobileFlex,
      tablet: tabletFlex,
      desktop: desktopFlex,
    );
  }
}

class ResponsiveVisibility {
  ResponsiveVisibility._();

  static bool showOnMobile(BuildContext context) {
    return Breakpoints.isMobile(context);
  }

  static bool showOnTablet(BuildContext context) {
    return Breakpoints.isTablet(context);
  }

  static bool showOnDesktop(BuildContext context) {
    return Breakpoints.isDesktop(context);
  }

  static bool hideOnMobile(BuildContext context) {
    return !Breakpoints.isMobile(context);
  }

  static bool hideOnTablet(BuildContext context) {
    return !Breakpoints.isTablet(context);
  }

  static bool hideOnDesktop(BuildContext context) {
    return !Breakpoints.isDesktop(context);
  }

  static bool showOnTabletUp(BuildContext context) {
    return Breakpoints.isTabletOrLarger(context);
  }

  static bool showOnMobileTablet(BuildContext context) {
    return Breakpoints.isMobileOrTablet(context);
  }
}

extension ResponsiveSizeExtension on num {
  double wp(BuildContext context) {
    return ResponsiveSize.widthPercent(context, toDouble());
  }

  double hp(BuildContext context) {
    return ResponsiveSize.heightPercent(context, toDouble());
  }

  double rfs(BuildContext context) {
    return ResponsiveSize.fontSize(context, toDouble());
  }
}
