/// Created by Haoyi on 2022/5/26

part of 'design_spec.dart';

class SpecMode {
  static const useGet = 0; // XX.get()
  static const useContext = 1; // XX.of(context)
  static const useSize = 2; // XX.from(size)
  static const nested = 3; // XX.create(size)
}

class DesignSpec {
  final double width;
  final double height;
  final int specMode;
  @Deprecated("在2.0.5之后，该参数将会移除，使用SpecMode中的useNested代替")
  final bool nestedSpec;
  final double? textScaleFactor;

  const DesignSpec(
      {required this.width,
      required this.height,
      this.specMode = SpecMode.useGet,
      this.nestedSpec = false,
      this.textScaleFactor});
}

abstract class SpecField {}

abstract class SpecValueField implements SpecField {}

abstract class SpecUiField implements SpecField {}

class SpecOrigin implements SpecValueField {
  final double value;

  const SpecOrigin(this.value);
}

class SpecHeight implements SpecValueField {
  final double height;
  final bool consistent;

  const SpecHeight(this.height, {this.consistent = false});
}

class SpecVertical implements SpecValueField {
  final double vertical;
  final bool relative;
  final bool consistent;

  const SpecVertical(this.vertical, {this.relative = false, this.consistent = false});
}

class SpecWidth implements SpecValueField {
  final double width;

  const SpecWidth(this.width);
}

class SpecHorizontal implements SpecValueField {
  final double horizontal;
  final bool relative;

  const SpecHorizontal(this.horizontal, {this.relative = false});
}

class SpecList implements SpecUiField {
  final List<SpecValueField> list;

  const SpecList(this.list);
}

class SpecFontSize implements SpecValueField {
  final double fontSize;

  const SpecFontSize(this.fontSize);
}

class SpecAbsoluteFontSize implements SpecValueField {
  final double fontSize;
  final bool consistent;

  const SpecAbsoluteFontSize(this.fontSize, {this.consistent = false});
}

class SpecStatusBarHeight implements SpecValueField {
  final double ifAbsent;
  final bool wrappedInSafeArea;

  const SpecStatusBarHeight(this.ifAbsent, {this.wrappedInSafeArea = false});
}

class SpecNavigationBarHeight implements SpecValueField {
  final double ifAbsent;
  final bool wrappedInSafeArea;

  const SpecNavigationBarHeight(this.ifAbsent, {this.wrappedInSafeArea = false});
}

class CombinedSpec implements SpecValueField {
  final SpecValueField spec1;
  final SpecValueField spec2;

  const CombinedSpec(this.spec1, this.spec2);
}

class SpecOffset implements SpecUiField {
  final SpecValueField dx;
  final SpecValueField dy;
  final bool relative;

  const SpecOffset(this.dx, this.dy, {this.relative = false});
}

class SpecSize implements SpecUiField {
  final SpecValueField width;
  final SpecValueField height;

  const SpecSize(this.width, this.height);
}

class SpecAspectHeightSize implements SpecUiField {
  final double height;
  final double aspectRatio;

  const SpecAspectHeightSize(this.height, this.aspectRatio);
}

class SpecAspectWidthSize implements SpecUiField {
  final double width;
  final double aspectRatio;

  const SpecAspectWidthSize(this.width, this.aspectRatio);
}

class SpecRect implements SpecUiField {
  final SpecValueField left;
  final SpecValueField top;
  final SpecValueField? width;
  final SpecValueField? height;
  final SpecValueField? right;
  final SpecValueField? bottom;
  final bool relative;

  const SpecRect.fromLTRB(this.left, this.top, this.right, this.bottom, {this.relative = false})
      : width = null,
        height = null;

  const SpecRect.fromLTWH(this.left, this.top, this.width, this.height, {this.relative = false})
      : right = null,
        bottom = null;
}

class SpecRRect implements SpecUiField {
  final SpecValueField left;
  final SpecValueField top;
  final SpecValueField? right;
  final SpecValueField? bottom;
  final SpecValueField? width;
  final SpecValueField? height;
  final SpecRadius radius;
  final bool relative;

  const SpecRRect.fromLTRBR(this.left, this.top, this.right, this.bottom, this.radius,
      {this.relative = false})
      : width = null,
        height = null;

  const SpecRRect.fromLTWHR(this.left, this.top, this.width, this.height, this.radius,
      {this.relative = false})
      : right = null,
        bottom = null;
}

class SpecRadius implements SpecUiField {
  final SpecValueField topStart;

  final SpecValueField topEnd;

  final SpecValueField bottomStart;

  final SpecValueField bottomEnd;

  const SpecRadius.circular(SpecValueField radius)
      : topStart = radius,
        topEnd = radius,
        bottomStart = radius,
        bottomEnd = radius;

  const SpecRadius.vertical(
      {SpecValueField top = const SpecOrigin(0), SpecValueField bottom = const SpecOrigin(0)})
      : topStart = top,
        topEnd = top,
        bottomStart = bottom,
        bottomEnd = bottom;

  const SpecRadius.horizontal(
      {SpecValueField start = const SpecOrigin(0), SpecValueField end = const SpecOrigin(0)})
      : topStart = start,
        topEnd = end,
        bottomStart = start,
        bottomEnd = end;

  const SpecRadius.only(
      {this.topStart = const SpecOrigin(0),
      this.topEnd = const SpecOrigin(0),
      this.bottomStart = const SpecOrigin(0),
      this.bottomEnd = const SpecOrigin(0)});
}

class SpecEdgeInsets implements SpecUiField {
  final SpecValueField start;
  final SpecValueField end;
  final SpecValueField top;
  final SpecValueField bottom;

  const SpecEdgeInsets.only(
      {this.start = const SpecOrigin(0),
      this.end = const SpecOrigin(0),
      this.top = const SpecOrigin(0),
      this.bottom = const SpecOrigin(0)});

  const SpecEdgeInsets.symmetric(
      {SpecValueField vertical = const SpecOrigin(0),
      SpecValueField horizontal = const SpecOrigin(0)})
      : start = horizontal,
        end = horizontal,
        top = vertical,
        bottom = vertical;

  const SpecEdgeInsets.all(SpecValueField value)
      : start = value,
        end = value,
        top = value,
        bottom = value;
}

class NestedSpec {
  final double designWidth;
  final double designHeight;
  final double widthUpperLimit;
  final double widthLowerLimit; // 真实最大尺寸
  final double heightUpperLimit;
  final double heightLowerLimit; // 真实最大尺寸
  final bool consistentWidth;
  final bool consistentHeight;

  const NestedSpec(this.designWidth, this.designHeight,
      {this.widthUpperLimit = 0xFFFFFFFF,
      this.widthLowerLimit = 0,
      this.heightUpperLimit = 0xFFFFFFFF,
      this.heightLowerLimit = 0,
      this.consistentWidth = false,
      this.consistentHeight = false});
}

class NestedAspectSpec {
  final double aspectRatio;
  final double relativeWidthScale;
  final double widthUpperLimit;
  final double widthLowerLimit; // 真实最大尺寸

  const NestedAspectSpec(this.aspectRatio, this.relativeWidthScale,
      {this.widthUpperLimit = 0xFFFFFFFF, this.widthLowerLimit = 0});
}

class NestedAspectHeightSpec {
  final double height;
  final double aspectRatio;

  const NestedAspectHeightSpec(this.height, this.aspectRatio);
}

class NestedAspectWidthSpec {
  final double width;
  final double aspectRatio;

  const NestedAspectWidthSpec(this.width, this.aspectRatio);
}
