// 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' as ui show lerpDouble;

import 'package:flutter/foundation.dart';

import 'alignment.dart';
import 'basic_types.dart';

/// An offset that's expressed as a fraction of a [Size].
///
/// `FractionalOffset(1.0, 0.0)` represents the top right of the [Size].
///
/// `FractionalOffset(0.0, 1.0)` represents the bottom left of the [Size].
///
/// `FractionalOffset(0.5, 2.0)` represents a point half way across the [Size],
/// below the bottom of the rectangle by the height of the [Size].
///
/// The [FractionalOffset] class specifies offsets in terms of a distance from
/// the top left, regardless of the [TextDirection].
///
/// ## Design discussion
///
/// [FractionalOffset] and [Alignment] are two different representations of the
/// same information: the location within a rectangle relative to the size of
/// the rectangle. The difference between the two classes is in the coordinate
/// system they use to represent the location.
///
/// [FractionalOffset] uses a coordinate system with an origin in the top-left
/// corner of the rectangle whereas [Alignment] uses a coordinate system with an
/// origin in the center of the rectangle.
///
/// Historically, [FractionalOffset] predates [Alignment]. When we attempted to
/// make a version of [FractionalOffset] that adapted to the [TextDirection], we
/// ran into difficulty because placing the origin in the top-left corner
/// introduced a left-to-right bias that was hard to remove.
///
/// By placing the origin in the center, [Alignment] and [AlignmentDirectional]
/// are able to use the same origin, which means we can use a linear function to
/// resolve an [AlignmentDirectional] into an [Alignment] in both
/// [TextDirection.rtl] and [TextDirection.ltr].
///
/// [Alignment] is better for most purposes than [FractionalOffset] and should
/// be used instead of [FractionalOffset]. We continue to implement
/// [FractionalOffset] to support code that predates [Alignment].
///
/// See also:
///
///  * [Alignment], which uses a coordinate system based on the center of the
///    rectangle instead of the top left corner of the rectangle.
@immutable
class FractionalOffset extends Alignment {
  /// Creates a fractional offset.
  ///
  /// The [dx] and [dy] arguments must not be null.
  const FractionalOffset(double dx, double dy)
    : assert(dx != null),
      assert(dy != null),
      super(dx * 2.0 - 1.0, dy * 2.0 - 1.0);

  /// Creates a fractional offset from a specific offset and size.
  ///
  /// The returned [FractionalOffset] describes the position of the
  /// [Offset] in the [Size], as a fraction of the [Size].
  factory FractionalOffset.fromOffsetAndSize(Offset offset, Size size) {
    assert(size != null);
    assert(offset != null);
    return FractionalOffset(
      offset.dx / size.width,
      offset.dy / size.height,
    );
  }

  /// Creates a fractional offset from a specific offset and rectangle.
  ///
  /// The offset is assumed to be relative to the same origin as the rectangle.
  ///
  /// If the offset is relative to the top left of the rectangle, use [new
  /// FractionalOffset.fromOffsetAndSize] instead, passing `rect.size`.
  ///
  /// The returned [FractionalOffset] describes the position of the
  /// [Offset] in the [Rect], as a fraction of the [Rect].
  factory FractionalOffset.fromOffsetAndRect(Offset offset, Rect rect) {
    return FractionalOffset.fromOffsetAndSize(
      offset - rect.topLeft,
      rect.size,
    );
  }

  /// The distance fraction in the horizontal direction.
  ///
  /// A value of 0.0 corresponds to the leftmost edge. A value of 1.0
  /// corresponds to the rightmost edge. Values are not limited to that range;
  /// negative values represent positions to the left of the left edge, and
  /// values greater than 1.0 represent positions to the right of the right
  /// edge.
  double get dx => (x + 1.0) / 2.0;

  /// The distance fraction in the vertical direction.
  ///
  /// A value of 0.0 corresponds to the topmost edge. A value of 1.0 corresponds
  /// to the bottommost edge. Values are not limited to that range; negative
  /// values represent positions above the top, and values greater than 1.0
  /// represent positions below the bottom.
  double get dy => (y + 1.0) / 2.0;

  /// The top left corner.
  static const FractionalOffset topLeft = FractionalOffset(0.0, 0.0);

  /// The center point along the top edge.
  static const FractionalOffset topCenter = FractionalOffset(0.5, 0.0);

  /// The top right corner.
  static const FractionalOffset topRight = FractionalOffset(1.0, 0.0);

  /// The center point along the left edge.
  static const FractionalOffset centerLeft = FractionalOffset(0.0, 0.5);

  /// The center point, both horizontally and vertically.
  static const FractionalOffset center = FractionalOffset(0.5, 0.5);

  /// The center point along the right edge.
  static const FractionalOffset centerRight = FractionalOffset(1.0, 0.5);

  /// The bottom left corner.
  static const FractionalOffset bottomLeft = FractionalOffset(0.0, 1.0);

  /// The center point along the bottom edge.
  static const FractionalOffset bottomCenter = FractionalOffset(0.5, 1.0);

  /// The bottom right corner.
  static const FractionalOffset bottomRight = FractionalOffset(1.0, 1.0);

  @override
  Alignment operator -(Alignment other) {
    if (other is! FractionalOffset)
      return super - other;
    return FractionalOffset(dx - other.dx, dy - other.dy);
  }

  @override
  Alignment operator +(Alignment other) {
    if (other is! FractionalOffset)
      return super + other;
    return FractionalOffset(dx + other.dx, dy + other.dy);
  }

  @override
  FractionalOffset operator -() {
    return FractionalOffset(-dx, -dy);
  }

  @override
  FractionalOffset operator *(double other) {
    return FractionalOffset(dx * other, dy * other);
  }

  @override
  FractionalOffset operator /(double other) {
    return FractionalOffset(dx / other, dy / other);
  }

  @override
  FractionalOffset operator ~/(double other) {
    return FractionalOffset((dx ~/ other).toDouble(), (dy ~/ other).toDouble());
  }

  @override
  FractionalOffset operator %(double other) {
    return FractionalOffset(dx % other, dy % other);
  }

  /// Linearly interpolate between two [FractionalOffset]s.
  ///
  /// If either is null, this function interpolates from [FractionalOffset.center].
  ///
  /// {@macro dart.ui.shadow.lerp}
  static FractionalOffset? lerp(FractionalOffset? a, FractionalOffset? b, double t) {
    assert(t != null);
    if (a == null && b == null)
      return null;
    if (a == null)
      return FractionalOffset(ui.lerpDouble(0.5, b!.dx, t)!, ui.lerpDouble(0.5, b.dy, t)!);
    if (b == null)
      return FractionalOffset(ui.lerpDouble(a.dx, 0.5, t)!, ui.lerpDouble(a.dy, 0.5, t)!);
    return FractionalOffset(ui.lerpDouble(a.dx, b.dx, t)!, ui.lerpDouble(a.dy, b.dy, t)!);
  }

  @override
  String toString() {
    return 'FractionalOffset(${dx.toStringAsFixed(1)}, '
                            '${dy.toStringAsFixed(1)})';
  }
}
