// 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:math' as math;

import 'package:flutter/painting.dart';
import 'package:flutter_test/flutter_test.dart';

void approxExpect(Alignment a, Alignment b) {
  expect(a.x, moreOrLessEquals(b.x));
  expect(a.y, moreOrLessEquals(b.y));
}

void main() {
  test('Alignment control test', () {
    const Alignment alignment = Alignment(0.5, 0.25);

    expect(alignment, hasOneLineDescription);
    expect(alignment.hashCode, equals(const Alignment(0.5, 0.25).hashCode));

    expect(alignment / 2.0, const Alignment(0.25, 0.125));
    expect(alignment ~/ 2.0, Alignment.center);
    expect(alignment % 5.0, const Alignment(0.5, 0.25));
  });

  test('Alignment.lerp()', () {
    const Alignment a = Alignment.topLeft;
    const Alignment b = Alignment.topCenter;
    expect(Alignment.lerp(a, b, 0.25), equals(const Alignment(-0.75, -1.0)));

    expect(Alignment.lerp(null, null, 0.25), isNull);
    expect(Alignment.lerp(null, b, 0.25), equals(const Alignment(0.0, -0.25)));
    expect(Alignment.lerp(a, null, 0.25), equals(const Alignment(-0.75, -0.75)));
  });

  test('AlignmentGeometry invariants', () {
    const AlignmentDirectional topStart = AlignmentDirectional.topStart;
    const AlignmentDirectional topEnd = AlignmentDirectional.topEnd;
    const Alignment center = Alignment.center;
    const Alignment topLeft = Alignment.topLeft;
    const Alignment topRight = Alignment.topRight;
    final List<double> numbers = <double>[0.0, 1.0, -1.0, 2.0, 0.25, 0.5, 100.0, -999.75];

    expect((topEnd * 0.0).add(topRight * 0.0), center);
    expect(topEnd.add(topRight) * 0.0, (topEnd * 0.0).add(topRight * 0.0));
    expect(topStart.add(topLeft), topLeft.add(topStart));
    expect(topStart.add(topLeft).resolve(TextDirection.ltr), (topStart.resolve(TextDirection.ltr)) + topLeft);
    expect(topStart.add(topLeft).resolve(TextDirection.rtl), (topStart.resolve(TextDirection.rtl)) + topLeft);
    expect(topStart.add(topLeft).resolve(TextDirection.ltr), topStart.resolve(TextDirection.ltr).add(topLeft));
    expect(topStart.add(topLeft).resolve(TextDirection.rtl), topStart.resolve(TextDirection.rtl).add(topLeft));
    expect(topStart.resolve(TextDirection.ltr), topLeft);
    expect(topStart.resolve(TextDirection.rtl), topRight);
    expect(topEnd * 0.0, center);
    expect(topLeft * 0.0, center);
    expect(topStart * 1.0, topStart);
    expect(topEnd * 1.0, topEnd);
    expect(topLeft * 1.0, topLeft);
    expect(topRight * 1.0, topRight);
    for (final double n in numbers) {
      expect((topStart * n).add(topStart), topStart * (n + 1.0));
      expect((topEnd * n).add(topEnd), topEnd * (n + 1.0));
      for (final double m in numbers)
        expect((topStart * n).add(topStart * m), topStart * (n + m));
    }
    expect(topStart + topStart + topStart, topStart * 3.0); // without using "add"
    for (final TextDirection x in TextDirection.values) {
      expect((topEnd * 0.0).add(topRight * 0.0).resolve(x), center.add(center).resolve(x));
      expect((topEnd * 0.0).add(topLeft).resolve(x), center.add(topLeft).resolve(x));
      expect((topEnd * 0.0).resolve(x).add(topLeft.resolve(x)), center.resolve(x).add(topLeft.resolve(x)));
      expect((topEnd * 0.0).resolve(x).add(topLeft), center.resolve(x).add(topLeft));
      expect((topEnd * 0.0).resolve(x), center.resolve(x));
    }
    expect(topStart, isNot(topLeft));
    expect(topEnd, isNot(topLeft));
    expect(topStart, isNot(topRight));
    expect(topEnd, isNot(topRight));
    expect(topStart.add(topLeft), isNot(topLeft));
    expect(topStart.add(topLeft), isNot(topStart));
  });

  test('AlignmentGeometry.resolve()', () {
    expect(const AlignmentDirectional(0.25, 0.3).resolve(TextDirection.ltr), const Alignment(0.25, 0.3));
    expect(const AlignmentDirectional(0.25, 0.3).resolve(TextDirection.rtl), const Alignment(-0.25, 0.3));
    expect(const AlignmentDirectional(-0.25, 0.3).resolve(TextDirection.ltr), const Alignment(-0.25, 0.3));
    expect(const AlignmentDirectional(-0.25, 0.3).resolve(TextDirection.rtl), const Alignment(0.25, 0.3));
    expect(const AlignmentDirectional(1.25, 0.3).resolve(TextDirection.ltr), const Alignment(1.25, 0.3));
    expect(const AlignmentDirectional(1.25, 0.3).resolve(TextDirection.rtl), const Alignment(-1.25, 0.3));
    expect(const AlignmentDirectional(0.5, -0.3).resolve(TextDirection.ltr), const Alignment(0.5, -0.3));
    expect(const AlignmentDirectional(0.5, -0.3).resolve(TextDirection.rtl), const Alignment(-0.5, -0.3));
    expect(AlignmentDirectional.center.resolve(TextDirection.ltr), Alignment.center);
    expect(AlignmentDirectional.center.resolve(TextDirection.rtl), Alignment.center);
    expect(AlignmentDirectional.bottomEnd.resolve(TextDirection.ltr), Alignment.bottomRight);
    expect(AlignmentDirectional.bottomEnd.resolve(TextDirection.rtl), Alignment.bottomLeft);
    expect(AlignmentDirectional(nonconst(1.0), 2.0), AlignmentDirectional(nonconst(1.0), 2.0));
    expect(const AlignmentDirectional(1.0, 2.0), isNot(const AlignmentDirectional(2.0, 1.0)));
    expect(
      AlignmentDirectional.centerStart.resolve(TextDirection.ltr),
      AlignmentDirectional.centerEnd.resolve(TextDirection.rtl),
    );
    expect(
      AlignmentDirectional.centerStart.resolve(TextDirection.ltr),
      isNot(AlignmentDirectional.centerEnd.resolve(TextDirection.ltr)),
    );
    expect(
      AlignmentDirectional.centerEnd.resolve(TextDirection.ltr),
      isNot(AlignmentDirectional.centerEnd.resolve(TextDirection.rtl)),
    );
  });

  test('AlignmentGeometry.lerp ad hoc tests', () {
    final AlignmentGeometry mixed1 = const Alignment(10.0, 20.0).add(const AlignmentDirectional(30.0, 50.0));
    final AlignmentGeometry mixed2 = const Alignment(70.0, 110.0).add(const AlignmentDirectional(130.0, 170.0));
    final AlignmentGeometry mixed3 = const Alignment(25.0, 42.5).add(const AlignmentDirectional(55.0, 80.0));

    for (final TextDirection direction in TextDirection.values) {
      expect(AlignmentGeometry.lerp(mixed1, mixed2, 0.0)!.resolve(direction), mixed1.resolve(direction));
      expect(AlignmentGeometry.lerp(mixed1, mixed2, 1.0)!.resolve(direction), mixed2.resolve(direction));
      expect(AlignmentGeometry.lerp(mixed1, mixed2, 0.25)!.resolve(direction), mixed3.resolve(direction));
    }
  });

  test('lerp commutes with resolve', () {
    final List<AlignmentGeometry?> offsets = <AlignmentGeometry?>[
      Alignment.topLeft,
      Alignment.topCenter,
      Alignment.topRight,
      AlignmentDirectional.topStart,
      AlignmentDirectional.topCenter,
      AlignmentDirectional.topEnd,
      Alignment.centerLeft,
      Alignment.center,
      Alignment.centerRight,
      AlignmentDirectional.centerStart,
      AlignmentDirectional.center,
      AlignmentDirectional.centerEnd,
      Alignment.bottomLeft,
      Alignment.bottomCenter,
      Alignment.bottomRight,
      AlignmentDirectional.bottomStart,
      AlignmentDirectional.bottomCenter,
      AlignmentDirectional.bottomEnd,
      const Alignment(-1.0, 0.65),
      const AlignmentDirectional(-1.0, 0.45),
      const AlignmentDirectional(0.125, 0.625),
      const Alignment(0.25, 0.875),
      const Alignment(0.0625, 0.5625).add(const AlignmentDirectional(0.1875, 0.6875)),
      const AlignmentDirectional(2.0, 3.0),
      const Alignment(2.0, 3.0),
      const Alignment(2.0, 3.0).add(const AlignmentDirectional(5.0, 3.0)),
      const Alignment(10.0, 20.0).add(const AlignmentDirectional(30.0, 50.0)),
      const Alignment(70.0, 110.0).add(const AlignmentDirectional(130.0, 170.0)),
      const Alignment(25.0, 42.5).add(const AlignmentDirectional(55.0, 80.0)),
      null,
    ];

    final List<double> times = <double>[ 0.25, 0.5, 0.75 ];

    for (final TextDirection direction in TextDirection.values) {
      final Alignment defaultValue = AlignmentDirectional.center.resolve(direction);
      for (final AlignmentGeometry? a in offsets) {
        final Alignment resolvedA = a?.resolve(direction) ?? defaultValue;
        for (final AlignmentGeometry? b in offsets) {
          final Alignment resolvedB = b?.resolve(direction) ?? defaultValue;
          approxExpect(Alignment.lerp(resolvedA, resolvedB, 0.0)!, resolvedA);
          approxExpect(Alignment.lerp(resolvedA, resolvedB, 1.0)!, resolvedB);
          approxExpect((AlignmentGeometry.lerp(a, b, 0.0) ?? defaultValue).resolve(direction), resolvedA);
          approxExpect((AlignmentGeometry.lerp(a, b, 1.0) ?? defaultValue).resolve(direction), resolvedB);
          for (final double t in times) {
            assert(t > 0.0);
            assert(t < 1.0);
            final Alignment value = (AlignmentGeometry.lerp(a, b, t) ?? defaultValue).resolve(direction);
            approxExpect(value, Alignment.lerp(resolvedA, resolvedB, t)!);
            final double minDX = math.min(resolvedA.x, resolvedB.x);
            final double maxDX = math.max(resolvedA.x, resolvedB.x);
            final double minDY = math.min(resolvedA.y, resolvedB.y);
            final double maxDY = math.max(resolvedA.y, resolvedB.y);
            expect(value.x, inInclusiveRange(minDX, maxDX));
            expect(value.y, inInclusiveRange(minDY, maxDY));
          }
        }
      }
    }
  });

  test('AlignmentGeometry add/subtract', () {
    const AlignmentGeometry directional = AlignmentDirectional(1.0, 2.0);
    const AlignmentGeometry normal = Alignment(3.0, 5.0);
    expect(directional.add(normal).resolve(TextDirection.ltr), const Alignment(4.0, 7.0));
    expect(directional.add(normal).resolve(TextDirection.rtl), const Alignment(2.0, 7.0));
    expect(normal.add(normal), normal * 2.0);
    expect(directional.add(directional), directional * 2.0);
  });

  test('AlignmentGeometry operators', () {
    expect(const AlignmentDirectional(1.0, 2.0) * 2.0, const AlignmentDirectional(2.0, 4.0));
    expect(const AlignmentDirectional(1.0, 2.0) / 2.0, const AlignmentDirectional(0.5, 1.0));
    expect(const AlignmentDirectional(1.0, 2.0) % 2.0, AlignmentDirectional.centerEnd);
    expect(const AlignmentDirectional(1.0, 2.0) ~/ 2.0, AlignmentDirectional.bottomCenter);
    for (final TextDirection direction in TextDirection.values) {
      expect(Alignment.center.add(const AlignmentDirectional(1.0, 2.0) * 2.0).resolve(direction), const AlignmentDirectional(2.0, 4.0).resolve(direction));
      expect(Alignment.center.add(const AlignmentDirectional(1.0, 2.0) / 2.0).resolve(direction), const AlignmentDirectional(0.5, 1.0).resolve(direction));
      expect(Alignment.center.add(const AlignmentDirectional(1.0, 2.0) % 2.0).resolve(direction), AlignmentDirectional.centerEnd.resolve(direction));
      expect(Alignment.center.add(const AlignmentDirectional(1.0, 2.0) ~/ 2.0).resolve(direction), AlignmentDirectional.bottomCenter.resolve(direction));
    }
    expect(const Alignment(1.0, 2.0) * 2.0, const Alignment(2.0, 4.0));
    expect(const Alignment(1.0, 2.0) / 2.0, const Alignment(0.5, 1.0));
    expect(const Alignment(1.0, 2.0) % 2.0, Alignment.centerRight);
    expect(const Alignment(1.0, 2.0) ~/ 2.0, Alignment.bottomCenter);
  });

  test('AlignmentGeometry operators', () {
    expect(const Alignment(1.0, 2.0) + const Alignment(3.0, 5.0), const Alignment(4.0, 7.0));
    expect(const Alignment(1.0, 2.0) - const Alignment(3.0, 5.0), const Alignment(-2.0, -3.0));
    expect(const AlignmentDirectional(1.0, 2.0) + const AlignmentDirectional(3.0, 5.0), const AlignmentDirectional(4.0, 7.0));
    expect(const AlignmentDirectional(1.0, 2.0) - const AlignmentDirectional(3.0, 5.0), const AlignmentDirectional(-2.0, -3.0));
  });

  test('AlignmentGeometry toString', () {
    expect(const Alignment(1.0001, 2.0001).toString(), 'Alignment(1.0, 2.0)');
    expect(Alignment.center.toString(), 'Alignment.center');
    expect(Alignment.bottomLeft.add(AlignmentDirectional.centerEnd).toString(), 'Alignment.bottomLeft + AlignmentDirectional.centerEnd');
    expect(const Alignment(0.0001, 0.0001).toString(), 'Alignment(0.0, 0.0)');
    expect(Alignment.center.toString(), 'Alignment.center');
    expect(AlignmentDirectional.center.toString(), 'AlignmentDirectional.center');
    expect(Alignment.bottomRight.add(AlignmentDirectional.bottomEnd).toString(), 'Alignment(1.0, 2.0) + AlignmentDirectional.centerEnd');
  });
}
