// Copyright 2017 The Chromium 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 'basic_types.dart';

/// Base class for [Alignment] that allows for text-direction aware
/// resolution.
///
/// A property or argument of this type accepts classes created either with [new
/// Alignment] and its variants, or [new AlignmentDirectional].
///
/// To convert an [AlignmentGeometry] object of indeterminate type into an
/// [Alignment] object, call the [resolve] method.
@immutable
abstract class AlignmentGeometry {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const AlignmentGeometry();

  double get _x;

  double get _start;

  double get _y;

  /// Returns the sum of two [AlignmentGeometry] objects.
  ///
  /// If you know you are adding two [Alignment] or two [AlignmentDirectional]
  /// objects, consider using the `+` operator instead, which always returns an
  /// object of the same type as the operands, and is typed accordingly.
  ///
  /// If [add] is applied to two objects of the same type ([Alignment] or
  /// [AlignmentDirectional]), an object of that type will be returned (though
  /// this is not reflected in the type system). Otherwise, an object
  /// representing a combination of both is returned. That object can be turned
  /// into a concrete [Alignment] using [resolve].
  AlignmentGeometry add(AlignmentGeometry other) {
    return _MixedAlignment(
      _x + other._x,
      _start + other._start,
      _y + other._y,
    );
  }

  /// Returns the negation of the given [AlignmentGeometry] object.
  ///
  /// This is the same as multiplying the object by -1.0.
  ///
  /// This operator returns an object of the same type as the operand.
  AlignmentGeometry operator -();

  /// Scales the [AlignmentGeometry] object in each dimension by the given factor.
  ///
  /// This operator returns an object of the same type as the operand.
  AlignmentGeometry operator *(double other);

  /// Divides the [AlignmentGeometry] object in each dimension by the given factor.
  ///
  /// This operator returns an object of the same type as the operand.
  AlignmentGeometry operator /(double other);

  /// Integer divides the [AlignmentGeometry] object in each dimension by the given factor.
  ///
  /// This operator returns an object of the same type as the operand.
  AlignmentGeometry operator ~/(double other);

  /// Computes the remainder in each dimension by the given factor.
  ///
  /// This operator returns an object of the same type as the operand.
  AlignmentGeometry operator %(double other);

  /// Linearly interpolate between two [AlignmentGeometry] objects.
  ///
  /// If either is null, this function interpolates from [Alignment.center], and
  /// the result is an object of the same type as the non-null argument.
  ///
  /// If [lerp] is applied to two objects of the same type ([Alignment] or
  /// [AlignmentDirectional]), an object of that type will be returned (though
  /// this is not reflected in the type system). Otherwise, an object
  /// representing a combination of both is returned. That object can be turned
  /// into a concrete [Alignment] using [resolve].
  ///
  /// {@macro dart.ui.shadow.lerp}
  static AlignmentGeometry lerp(AlignmentGeometry a, AlignmentGeometry b, double t) {
    assert(t != null);
    if (a == null && b == null)
      return null;
    if (a == null)
      return b * t;
    if (b == null)
      return a * (1.0 - t);
    if (a is Alignment && b is Alignment)
      return Alignment.lerp(a, b, t);
    if (a is AlignmentDirectional && b is AlignmentDirectional)
      return AlignmentDirectional.lerp(a, b, t);
    return _MixedAlignment(
      ui.lerpDouble(a._x, b._x, t),
      ui.lerpDouble(a._start, b._start, t),
      ui.lerpDouble(a._y, b._y, t),
    );
  }

  /// Convert this instance into an [Alignment], which uses literal
  /// coordinates (the `x` coordinate being explicitly a distance from the
  /// left).
  ///
  /// See also:
  ///
  ///  * [Alignment], for which this is a no-op (returns itself).
  ///  * [AlignmentDirectional], which flips the horizontal direction
  ///    based on the `direction` argument.
  Alignment resolve(TextDirection direction);

  @override
  String toString() {
    if (_start == 0.0)
      return Alignment._stringify(_x, _y);
    if (_x == 0.0)
      return AlignmentDirectional._stringify(_start, _y);
    return Alignment._stringify(_x, _y) + ' + ' + AlignmentDirectional._stringify(_start, 0.0);
  }

  @override
  bool operator ==(dynamic other) {
    if (other is! AlignmentGeometry)
      return false;
    final AlignmentGeometry typedOther = other;
    return _x == typedOther._x &&
           _start == typedOther._start &&
           _y == typedOther._y;
  }

  @override
  int get hashCode => hashValues(_x, _start, _y);
}

/// A point within a rectangle.
///
/// `Alignment(0.0, 0.0)` represents the center of the rectangle. The distance
/// from -1.0 to +1.0 is the distance from one side of the rectangle to the
/// other side of the rectangle. Therefore, 2.0 units horizontally (or
/// vertically) is equivalent to the width (or height) of the rectangle.
///
/// `Alignment(-1.0, -1.0)` represents the top left of the rectangle.
///
/// `Alignment(1.0, 1.0)` represents the bottom right of the rectangle.
///
/// `Alignment(0.0, 3.0)` represents a point that is horizontally centered with
/// respect to the rectangle and vertically below the bottom of the rectangle by
/// the height of the rectangle.
///
/// `Alignment(0.0, -0.5)` represents a point that is horizontally centered with
/// respect to the rectangle and vertically half way between the top edge and
/// the center.
///
/// `Alignment(x, y)` in a rectangle with height h and width w describes
/// the point (x * w/2 + w/2, y * h/2 + h/2) in the coordinate system of the
/// rectangle.
///
/// [Alignment] uses visual coordinates, which means increasing [x] moves the
/// point from left to right. To support layouts with a right-to-left
/// [TextDirection], consider using [AlignmentDirectional], in which the
/// direction the point moves when increasing the horizontal value depends on
/// the [TextDirection].
///
/// A variety of widgets use [Alignment] in their configuration, most
/// notably:
///
///  * [Align] positions a child according to an [Alignment].
///
/// See also:
///
///  * [AlignmentDirectional], which has a horizontal coordinate orientation
///    that depends on the [TextDirection].
///  * [AlignmentGeometry], which is an abstract type that is agnostic as to
///    whether the horizontal direction depends on the [TextDirection].
class Alignment extends AlignmentGeometry {
  /// Creates an alignment.
  ///
  /// The [x] and [y] arguments must not be null.
  const Alignment(this.x, this.y)
    : assert(x != null),
      assert(y != null);

  /// The distance fraction in the horizontal direction.
  ///
  /// A value of -1.0 corresponds to the leftmost edge. A value of 1.0
  /// corresponds to the rightmost edge. Values are not limited to that range;
  /// values less than -1.0 represent positions to the left of the left edge,
  /// and values greater than 1.0 represent positions to the right of the right
  /// edge.
  final double x;

  /// The distance fraction in the vertical direction.
  ///
  /// A value of -1.0 corresponds to the topmost edge. A value of 1.0
  /// corresponds to the bottommost edge. Values are not limited to that range;
  /// values less than -1.0 represent positions above the top, and values
  /// greater than 1.0 represent positions below the bottom.
  final double y;

  @override
  double get _x => x;

  @override
  double get _start => 0.0;

  @override
  double get _y => y;

  /// The top left corner.
  static const Alignment topLeft = Alignment(-1.0, -1.0);

  /// The center point along the top edge.
  static const Alignment topCenter = Alignment(0.0, -1.0);

  /// The top right corner.
  static const Alignment topRight = Alignment(1.0, -1.0);

  /// The center point along the left edge.
  static const Alignment centerLeft = Alignment(-1.0, 0.0);

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

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

  /// The bottom left corner.
  static const Alignment bottomLeft = Alignment(-1.0, 1.0);

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

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

  @override
  AlignmentGeometry add(AlignmentGeometry other) {
    if (other is Alignment)
      return this + other;
    return super.add(other);
  }

  /// Returns the difference between two [Alignment]s.
  Alignment operator -(Alignment other) {
    return Alignment(x - other.x, y - other.y);
  }

  /// Returns the sum of two [Alignment]s.
  Alignment operator +(Alignment other) {
    return Alignment(x + other.x, y + other.y);
  }

  /// Returns the negation of the given [Alignment].
  @override
  Alignment operator -() {
    return Alignment(-x, -y);
  }

  /// Scales the [Alignment] in each dimension by the given factor.
  @override
  Alignment operator *(double other) {
    return Alignment(x * other, y * other);
  }

  /// Divides the [Alignment] in each dimension by the given factor.
  @override
  Alignment operator /(double other) {
    return Alignment(x / other, y / other);
  }

  /// Integer divides the [Alignment] in each dimension by the given factor.
  @override
  Alignment operator ~/(double other) {
    return Alignment((x ~/ other).toDouble(), (y ~/ other).toDouble());
  }

  /// Computes the remainder in each dimension by the given factor.
  @override
  Alignment operator %(double other) {
    return Alignment(x % other, y % other);
  }

  /// Returns the offset that is this fraction in the direction of the given offset.
  Offset alongOffset(Offset other) {
    final double centerX = other.dx / 2.0;
    final double centerY = other.dy / 2.0;
    return Offset(centerX + x * centerX, centerY + y * centerY);
  }

  /// Returns the offset that is this fraction within the given size.
  Offset alongSize(Size other) {
    final double centerX = other.width / 2.0;
    final double centerY = other.height / 2.0;
    return Offset(centerX + x * centerX, centerY + y * centerY);
  }

  /// Returns the point that is this fraction within the given rect.
  Offset withinRect(Rect rect) {
    final double halfWidth = rect.width / 2.0;
    final double halfHeight = rect.height / 2.0;
    return Offset(
      rect.left + halfWidth + x * halfWidth,
      rect.top + halfHeight + y * halfHeight,
    );
  }

  /// Returns a rect of the given size, aligned within given rect as specified
  /// by this alignment.
  ///
  /// For example, a 100×100 size inscribed on a 200×200 rect using
  /// [Alignment.topLeft] would be the 100×100 rect at the top left of
  /// the 200×200 rect.
  Rect inscribe(Size size, Rect rect) {
    final double halfWidthDelta = (rect.width - size.width) / 2.0;
    final double halfHeightDelta = (rect.height - size.height) / 2.0;
    return Rect.fromLTWH(
      rect.left + halfWidthDelta + x * halfWidthDelta,
      rect.top + halfHeightDelta + y * halfHeightDelta,
      size.width,
      size.height,
    );
  }

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

  @override
  Alignment resolve(TextDirection direction) => this;

  static String _stringify(double x, double y) {
    if (x == -1.0 && y == -1.0)
      return 'topLeft';
    if (x == 0.0 && y == -1.0)
      return 'topCenter';
    if (x == 1.0 && y == -1.0)
      return 'topRight';
    if (x == -1.0 && y == 0.0)
      return 'centerLeft';
    if (x == 0.0 && y == 0.0)
      return 'center';
    if (x == 1.0 && y == 0.0)
      return 'centerRight';
    if (x == -1.0 && y == 1.0)
      return 'bottomLeft';
    if (x == 0.0 && y == 1.0)
      return 'bottomCenter';
    if (x == 1.0 && y == 1.0)
      return 'bottomRight';
    return 'Alignment(${x.toStringAsFixed(1)}, '
                     '${y.toStringAsFixed(1)})';
  }

  @override
  String toString() => _stringify(x, y);
}

/// An offset that's expressed as a fraction of a [Size], but whose horizontal
/// component is dependent on the writing direction.
///
/// This can be used to indicate an offset from the left in [TextDirection.ltr]
/// text and an offset from the right in [TextDirection.rtl] text without having
/// to be aware of the current text direction.
///
/// See also:
///
///  * [Alignment], a variant that is defined in physical terms (i.e.
///    whose horizontal component does not depend on the text direction).
class AlignmentDirectional extends AlignmentGeometry {
  /// Creates a directional alignment.
  ///
  /// The [start] and [y] arguments must not be null.
  const AlignmentDirectional(this.start, this.y)
    : assert(start != null),
      assert(y != null);

  /// The distance fraction in the horizontal direction.
  ///
  /// A value of -1.0 corresponds to the edge on the "start" side, which is the
  /// left side in [TextDirection.ltr] contexts and the right side in
  /// [TextDirection.rtl] contexts. A value of 1.0 corresponds to the opposite
  /// edge, the "end" side. Values are not limited to that range; values less
  /// than -1.0 represent positions beyond the start edge, and values greater than
  /// 1.0 represent positions beyond the end edge.
  ///
  /// This value is normalized into an [Alignment.x] value by the [resolve]
  /// method.
  final double start;

  /// The distance fraction in the vertical direction.
  ///
  /// A value of -1.0 corresponds to the topmost edge. A value of 1.0
  /// corresponds to the bottommost edge. Values are not limited to that range;
  /// values less than -1.0 represent positions above the top, and values
  /// greater than 1.0 represent positions below the bottom.
  ///
  /// This value is passed through to [Alignment.y] unmodified by the
  /// [resolve] method.
  final double y;

  @override
  double get _x => 0.0;

  @override
  double get _start => start;

  @override
  double get _y => y;

  /// The top corner on the "start" side.
  static const AlignmentDirectional topStart = AlignmentDirectional(-1.0, -1.0);

  /// The center point along the top edge.
  ///
  /// Consider using [Alignment.topCenter] instead, as it does not need
  /// to be [resolve]d to be used.
  static const AlignmentDirectional topCenter = AlignmentDirectional(0.0, -1.0);

  /// The top corner on the "end" side.
  static const AlignmentDirectional topEnd = AlignmentDirectional(1.0, -1.0);

  /// The center point along the "start" edge.
  static const AlignmentDirectional centerStart = AlignmentDirectional(-1.0, 0.0);

  /// The center point, both horizontally and vertically.
  ///
  /// Consider using [Alignment.center] instead, as it does not need to
  /// be [resolve]d to be used.
  static const AlignmentDirectional center = AlignmentDirectional(0.0, 0.0);

  /// The center point along the "end" edge.
  static const AlignmentDirectional centerEnd = AlignmentDirectional(1.0, 0.0);

  /// The bottom corner on the "start" side.
  static const AlignmentDirectional bottomStart = AlignmentDirectional(-1.0, 1.0);

  /// The center point along the bottom edge.
  ///
  /// Consider using [Alignment.bottomCenter] instead, as it does not
  /// need to be [resolve]d to be used.
  static const AlignmentDirectional bottomCenter = AlignmentDirectional(0.0, 1.0);

  /// The bottom corner on the "end" side.
  static const AlignmentDirectional bottomEnd = AlignmentDirectional(1.0, 1.0);

  @override
  AlignmentGeometry add(AlignmentGeometry other) {
    if (other is AlignmentDirectional)
      return this + other;
    return super.add(other);
  }

  /// Returns the difference between two [AlignmentDirectional]s.
  AlignmentDirectional operator -(AlignmentDirectional other) {
    return AlignmentDirectional(start - other.start, y - other.y);
  }

  /// Returns the sum of two [AlignmentDirectional]s.
  AlignmentDirectional operator +(AlignmentDirectional other) {
    return AlignmentDirectional(start + other.start, y + other.y);
  }

  /// Returns the negation of the given [AlignmentDirectional].
  @override
  AlignmentDirectional operator -() {
    return AlignmentDirectional(-start, -y);
  }

  /// Scales the [AlignmentDirectional] in each dimension by the given factor.
  @override
  AlignmentDirectional operator *(double other) {
    return AlignmentDirectional(start * other, y * other);
  }

  /// Divides the [AlignmentDirectional] in each dimension by the given factor.
  @override
  AlignmentDirectional operator /(double other) {
    return AlignmentDirectional(start / other, y / other);
  }

  /// Integer divides the [AlignmentDirectional] in each dimension by the given factor.
  @override
  AlignmentDirectional operator ~/(double other) {
    return AlignmentDirectional((start ~/ other).toDouble(), (y ~/ other).toDouble());
  }

  /// Computes the remainder in each dimension by the given factor.
  @override
  AlignmentDirectional operator %(double other) {
    return AlignmentDirectional(start % other, y % other);
  }

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

  @override
  Alignment resolve(TextDirection direction) {
    assert(direction != null);
    switch (direction) {
      case TextDirection.rtl:
        return Alignment(-start, y);
      case TextDirection.ltr:
        return Alignment(start, y);
    }
    return null;
  }

  static String _stringify(double start, double y) {
    if (start == -1.0 && y == -1.0)
      return 'AlignmentDirectional.topStart';
    if (start == 0.0 && y == -1.0)
      return 'AlignmentDirectional.topCenter';
    if (start == 1.0 && y == -1.0)
      return 'AlignmentDirectional.topEnd';
    if (start == -1.0 && y == 0.0)
      return 'AlignmentDirectional.centerStart';
    if (start == 0.0 && y == 0.0)
      return 'AlignmentDirectional.center';
    if (start == 1.0 && y == 0.0)
      return 'AlignmentDirectional.centerEnd';
    if (start == -1.0 && y == 1.0)
      return 'AlignmentDirectional.bottomStart';
    if (start == 0.0 && y == 1.0)
      return 'AlignmentDirectional.bottomCenter';
    if (start == 1.0 && y == 1.0)
      return 'AlignmentDirectional.bottomEnd';
    return 'AlignmentDirectional(${start.toStringAsFixed(1)}, '
                                '${y.toStringAsFixed(1)})';
  }

  @override
  String toString() => _stringify(start, y);
}

class _MixedAlignment extends AlignmentGeometry {
  const _MixedAlignment(this._x, this._start, this._y);

  @override
  final double _x;

  @override
  final double _start;

  @override
  final double _y;

  @override
  _MixedAlignment operator -() {
    return _MixedAlignment(
      -_x,
      -_start,
      -_y,
    );
  }

  @override
  _MixedAlignment operator *(double other) {
    return _MixedAlignment(
      _x * other,
      _start * other,
      _y * other,
    );
  }

  @override
  _MixedAlignment operator /(double other) {
    return _MixedAlignment(
      _x / other,
      _start / other,
      _y / other,
    );
  }

  @override
  _MixedAlignment operator ~/(double other) {
    return _MixedAlignment(
      (_x ~/ other).toDouble(),
      (_start ~/ other).toDouble(),
      (_y ~/ other).toDouble(),
    );
  }

  @override
  _MixedAlignment operator %(double other) {
    return _MixedAlignment(
      _x % other,
      _start % other,
      _y % other,
    );
  }

  @override
  Alignment resolve(TextDirection direction) {
    assert(direction != null);
    switch (direction) {
      case TextDirection.rtl:
        return Alignment(_x - _start, _y);
      case TextDirection.ltr:
        return Alignment(_x + _start, _y);
    }
    return null;
  }
}

/// The vertical alignment of text within an input box.
///
/// A single [y] value that can range from -1.0 to 1.0. -1.0 aligns to the top
/// of an input box so that the top of the first line of text fits within the
/// box and its padding. 0.0 aligns to the center of the box. 1.0 aligns so that
/// the bottom of the last line of text aligns with the bottom interior edge of
/// the input box.
///
/// See also:
///
///  * [TextField.textAlignVertical], which is passed on to the [InputDecorator].
///  * [CupertinoTextField.textAlignVertical], which behaves in the same way as
///    the parameter in TextField.
///  * [InputDecorator.textAlignVertical], which defines the alignment of
///    prefix, input, and suffix within an [InputDecorator].
class TextAlignVertical {
  /// Creates a TextAlignVertical from any y value between -1.0 and 1.0.
  const TextAlignVertical({
    @required this.y,
  }) : assert(y != null),
       assert(y >= -1.0 && y <= 1.0);

  /// A value ranging from -1.0 to 1.0 that defines the topmost and bottommost
  /// locations of the top and bottom of the input box.
  final double y;

  /// Aligns a TextField's input Text with the topmost location within a
  /// TextField's input box.
  static const TextAlignVertical top = TextAlignVertical(y: -1.0);
  /// Aligns a TextField's input Text to the center of the TextField.
  static const TextAlignVertical center = TextAlignVertical(y: 0.0);
  /// Aligns a TextField's input Text with the bottommost location within a
  /// TextField.
  static const TextAlignVertical bottom = TextAlignVertical(y: 1.0);

  @override
  String toString() {
    return '$runtimeType(y: $y)';
  }
}
