// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui' show lerpDouble;

import 'package:flutter/foundation.dart';

import 'basic_types.dart';
import 'borders.dart';
import 'edge_insets.dart';

/// Defines the relative size and alignment of one <LinearBorder> edge.
///
/// A [LinearBorder] defines a box outline as zero to four edges, each
/// of which is rendered as a single line. The width and color of the
/// lines is defined by [LinearBorder.side].
///
/// Each line's length is defined by [size], a value between 0.0 and 1.0
/// (the default) which defines the length as a percentage of the
/// length of a box edge.
///
/// When [size] is less than 1.0, the line is aligned within the
/// available space according to [alignment], a value between -1.0 and
/// 1.0.  The default is 0.0, which means centered, -1.0 means align on the
/// "start" side, and 1.0 means align on the "end" side. The meaning of
/// start and end depend on the current [TextDirection], see
/// [Directionality].
@immutable
class LinearBorderEdge {
  /// Defines one side of a [LinearBorder].
  ///
  /// The values of [size] and [alignment] must be between
  /// 0.0 and 1.0, and -1.0 and 1.0 respectively.
  const LinearBorderEdge({
    this.size = 1.0,
    this.alignment = 0.0,
  }) : assert(size >= 0.0 && size <= 1.0);

  /// A value between 0.0 and 1.0 that defines the length of the edge as a
  /// percentage of the length of the corresponding box
  /// edge. Default is 1.0.
  final double size;

  /// A value between -1.0 and 1.0 that defines how edges for which [size]
  /// is less than 1.0 are aligned relative to the corresponding box edge.
  ///
  ///  * -1.0, aligned in the "start" direction. That's left
  ///    for [TextDirection.ltr] and right for [TextDirection.rtl].
  ///  * 0.0, centered.
  ///  * 1.0, aligned in the "end" direction. That's right
  ///    for [TextDirection.ltr] and left for [TextDirection.rtl].
  final double alignment;

  /// Linearly interpolates between two [LinearBorder]s.
  ///
  /// If both `a` and `b` are null then null is returned. If `a` is null
  /// then we interpolate to `b` varying [size] from 0.0 to `b.size`. If `b`
  /// is null then we interpolate from `a` varying size from `a.size` to zero.
  /// Otherwise both values are interpolated.
  static LinearBorderEdge? lerp(LinearBorderEdge? a, LinearBorderEdge? b, double t) {
    if (identical(a, b)) {
      return a;
    }

    a ??= LinearBorderEdge(alignment: b!.alignment, size: 0);
    b ??= LinearBorderEdge(alignment: a.alignment, size: 0);

    return LinearBorderEdge(
      size: lerpDouble(a.size, b.size, t)!,
      alignment: lerpDouble(a.alignment, b.alignment, t)!,
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is LinearBorderEdge
        && other.size == size
        && other.alignment == alignment;
  }

  @override
  int get hashCode => Object.hash(size, alignment);

  @override
  String toString() {
    final StringBuffer s = StringBuffer('${objectRuntimeType(this, 'LinearBorderEdge')}(');
    if (size != 1.0 ) {
      s.write('size: $size');
    }
    if (alignment != 0) {
      final String comma = size != 1.0 ? ', ' : '';
      s.write('${comma}alignment: $alignment');
    }
    s.write(')');
    return s.toString();
  }
}

/// An [OutlinedBorder] like [BoxBorder] that allows one to define a rectangular (box) border
/// in terms of zero to four [LinearBorderEdge]s, each of which is rendered as a single line.
///
/// The color and width of each line are defined by [side]. When [LinearBorder] is used
/// with a class whose border sides and shape are defined by a [ButtonStyle], then a non-null
/// [ButtonStyle.side] will override the one specified here. For example the [LinearBorder]
/// in the [TextButton] example below adds a red underline to the button. This is because
/// TextButton's `side` parameter overrides the `side` property of its [ButtonStyle.shape].
///
/// ```dart
///  TextButton(
///    style: TextButton.styleFrom(
///      side: const BorderSide(color: Colors.red),
///      shape: const LinearBorder(
///        side: BorderSide(color: Colors.blue),
///        bottom: LinearBorderEdge(),
///      ),
///    ),
///    onPressed: () { },
///    child: const Text('Red LinearBorder'),
///  )
///```
///
/// This class resolves itself against the current [TextDirection] (see [Directionality]).
/// Start and end values resolve to left and right for [TextDirection.ltr] and to
/// right and left for [TextDirection.rtl].
///
/// Convenience constructors are included for the common case where just one edge is specified:
/// [LinearBorder.start], [LinearBorder.end], [LinearBorder.top], [LinearBorder.bottom].
class LinearBorder extends OutlinedBorder {
  /// Creates a rectangular box border that's rendered as zero to four lines.
  const LinearBorder({
    super.side,
    this.start,
    this.end,
    this.top,
    this.bottom,
  });

  /// Creates a rectangular box border with an edge on the left for [TextDirection.ltr]
  /// or on the right for [TextDirection.rtl].
  LinearBorder.start({
    super.side,
    double alignment = 0.0,
    double size = 1.0
  }) : start = LinearBorderEdge(alignment: alignment, size: size),
       end = null,
       top = null,
       bottom = null;

  /// Creates a rectangular box border with an edge on the right for [TextDirection.ltr]
  /// or on the left for [TextDirection.rtl].
  LinearBorder.end({
    super.side,
    double alignment = 0.0,
    double size = 1.0
  }) : start = null,
       end = LinearBorderEdge(alignment: alignment, size: size),
       top = null,
       bottom = null;

  /// Creates a rectangular box border with an edge on the top.
  LinearBorder.top({
    super.side,
    double alignment = 0.0,
    double size = 1.0
  }) : start = null,
       end = null,
       top = LinearBorderEdge(alignment: alignment, size: size),
       bottom = null;

  /// Creates a rectangular box border with an edge on the bottom.
  LinearBorder.bottom({
    super.side,
    double alignment = 0.0,
    double size = 1.0
  }) : start = null,
       end = null,
       top = null,
       bottom = LinearBorderEdge(alignment: alignment, size: size);

  /// No border.
  static const LinearBorder none = LinearBorder();

  /// Defines the left edge for [TextDirection.ltr] or the right
  /// for [TextDirection.rtl].
  final LinearBorderEdge? start;

  /// Defines the right edge for [TextDirection.ltr] or the left
  /// for [TextDirection.rtl].
  final LinearBorderEdge? end;

  /// Defines the top edge.
  final LinearBorderEdge? top;

  /// Defines the bottom edge.
  final LinearBorderEdge? bottom;

  @override
  LinearBorder scale(double t) {
    return LinearBorder(
      side: side.scale(t),
    );
  }

  @override
  EdgeInsetsGeometry get dimensions {
    final double width = side.width;
    return EdgeInsetsDirectional.fromSTEB(
      start == null ? 0.0 : width,
      top == null ? 0.0 : width,
      end == null ? 0.0 : width,
      bottom == null ? 0.0 : width,
    );
  }

  @override
  ShapeBorder? lerpFrom(ShapeBorder? a, double t) {
    if (a is LinearBorder) {
      return LinearBorder(
        side: BorderSide.lerp(a.side, side, t),
        start: LinearBorderEdge.lerp(a.start, start, t),
        end: LinearBorderEdge.lerp(a.end, end, t),
        top: LinearBorderEdge.lerp(a.top, top, t),
        bottom: LinearBorderEdge.lerp(a.bottom, bottom, t),
      );
    }
    return super.lerpFrom(a, t);
  }

  @override
  ShapeBorder? lerpTo(ShapeBorder? b, double t) {
    if (b is LinearBorder) {
      return LinearBorder(
        side: BorderSide.lerp(side, b.side, t),
        start: LinearBorderEdge.lerp(start, b.start, t),
        end: LinearBorderEdge.lerp(end, b.end, t),
        top: LinearBorderEdge.lerp(top, b.top, t),
        bottom: LinearBorderEdge.lerp(bottom, b.bottom, t),
      );
    }
    return super.lerpTo(b, t);
  }

  /// Returns a copy of this LinearBorder with the given fields replaced with
  /// the new values.
  @override
  LinearBorder copyWith({
    BorderSide? side,
    LinearBorderEdge? start,
    LinearBorderEdge? end,
    LinearBorderEdge? top,
    LinearBorderEdge? bottom,
  }) {
    return LinearBorder(
      side: side ?? this.side,
      start: start ?? this.start,
      end: end ?? this.end,
      top: top ?? this.top,
      bottom: bottom ?? this.bottom,
    );
  }

  @override
  Path getInnerPath(Rect rect, { TextDirection? textDirection }) {
    final Rect adjustedRect = dimensions.resolve(textDirection).deflateRect(rect);
    return Path()
      ..addRect(adjustedRect);
  }

  @override
  Path getOuterPath(Rect rect, { TextDirection? textDirection }) {
    return Path()
      ..addRect(rect);
  }

  @override
  void paint(Canvas canvas, Rect rect, { TextDirection? textDirection }) {
    final EdgeInsets insets = dimensions.resolve(textDirection);
    final bool rtl = textDirection == TextDirection.rtl;

    final Path path = Path();
    final Paint paint = Paint()
      ..strokeWidth = 0.0;

    void drawEdge(Rect rect, Color color) {
      paint.color = color;
      path.reset();
      path.moveTo(rect.left, rect.top);
      if (rect.width == 0.0) {
        paint.style = PaintingStyle.stroke;
        path.lineTo(rect.left, rect.bottom);
      } else if (rect.height == 0.0) {
        paint.style = PaintingStyle.stroke;
        path.lineTo(rect.right, rect.top);
      } else {
        paint.style = PaintingStyle.fill;
        path.lineTo(rect.right, rect.top);
        path.lineTo(rect.right, rect.bottom);
        path.lineTo(rect.left, rect.bottom);
      }
      canvas.drawPath(path, paint);
    }

    if (start != null && start!.size != 0.0 && side.style != BorderStyle.none) {
      final Rect insetRect = Rect.fromLTWH(rect.left, rect.top + insets.top, rect.width, rect.height - insets.vertical);
      final double x = rtl ? rect.right - insets.right : rect.left;
      final double width = rtl ? insets.right : insets.left;
      final double height = insetRect.height * start!.size;
      final double y = (insetRect.height - height) * ((start!.alignment + 1.0) / 2.0);
      final Rect r = Rect.fromLTWH(x, y, width, height);
      drawEdge(r, side.color);
    }

    if (end != null && end!.size != 0.0 && side.style != BorderStyle.none) {
      final Rect insetRect = Rect.fromLTWH(rect.left, rect.top + insets.top, rect.width, rect.height - insets.vertical);
      final double x = rtl ? rect.left : rect.right - insets.right;
      final double width = rtl ? insets.left : insets.right;
      final double height = insetRect.height * end!.size;
      final double y = (insetRect.height - height) * ((end!.alignment + 1.0) / 2.0);
      final Rect r = Rect.fromLTWH(x, y, width, height);
      drawEdge(r, side.color);
    }

    if (top != null && top!.size != 0.0 && side.style != BorderStyle.none) {
      final double width = rect.width * top!.size;
      final double startX = (rect.width - width) * ((top!.alignment + 1.0) / 2.0);
      final double x = rtl ? rect.width - startX - width : startX;
      final Rect r = Rect.fromLTWH(x, rect.top, width, insets.top);
      drawEdge(r, side.color);
    }

    if (bottom != null && bottom!.size != 0.0 && side.style != BorderStyle.none) {
      final double width = rect.width * bottom!.size;
      final double startX = (rect.width - width) * ((bottom!.alignment + 1.0) / 2.0);
      final double x = rtl ? rect.width - startX - width: startX;
      final Rect r = Rect.fromLTWH(x, rect.bottom - insets.bottom, width, side.width);
      drawEdge(r, side.color);
    }
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is LinearBorder
      && other.side == side
      && other.start == start
      && other.end == end
      && other.top == top
      && other.bottom == bottom;
  }

  @override
  int get hashCode => Object.hash(side, start, end, top, bottom);

  @override
  String toString() {
    if (this == LinearBorder.none) {
      return 'LinearBorder.none';
    }

    final StringBuffer s = StringBuffer('${objectRuntimeType(this, 'LinearBorder')}(side: $side');

    if (start != null ) {
      s.write(', start: $start');
    }
    if (end != null ) {
      s.write(', end: $end');
    }
    if (top != null ) {
      s.write(', top: $top');
    }
    if (bottom != null ) {
      s.write(', bottom: $bottom');
    }
    s.write(')');
    return s.toString();
  }
}
