// 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 [
  /// 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)})';
  }
}
