// 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 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

@immutable
class Pair<T> {
  const Pair(this.first, this.second);
  final T? first;
  final T second;

  @override
  bool operator ==(Object other) {
    return other is Pair<T> && other.first == first && other.second == second;
  }

  @override
  int get hashCode => hashValues(first, second);

  @override
  String toString() => '($first,$second)';
}

/// Widget that will layout one child in the top half of this widget's size
/// and the other child in the bottom half. It will swap which child is on top
/// and which is on bottom every time the widget is rendered.
abstract class Swapper extends RenderObjectWidget {
  const Swapper({ Key? key, this.stable, this.swapper }) : super(key: key);

  final Widget? stable;
  final Widget? swapper;

  @override
  SwapperElement createElement();

  @override
  RenderObject createRenderObject(BuildContext context) => RenderSwapper();
}

class SwapperWithProperOverrides extends Swapper {
  const SwapperWithProperOverrides({
    Key? key,
    Widget? stable,
    Widget? swapper,
  }) : super(key: key, stable: stable, swapper: swapper);

  @override
  SwapperElement createElement() => SwapperElementWithProperOverrides(this);
}

class SwapperWithNoOverrides extends Swapper {
  const SwapperWithNoOverrides({
    Key? key,
    Widget? stable,
    Widget? swapper,
  }) : super(key: key, stable: stable, swapper: swapper);

  @override
  SwapperElement createElement() => SwapperElementWithNoOverrides(this);
}

class SwapperWithDeprecatedOverrides extends Swapper {
  const SwapperWithDeprecatedOverrides({
    Key? key,
    Widget? stable,
    Widget? swapper,
  }) : super(key: key, stable: stable, swapper: swapper);

  @override
  SwapperElement createElement() => SwapperElementWithDeprecatedOverrides(this);
}

abstract class SwapperElement extends RenderObjectElement {
  SwapperElement(Swapper widget) : super(widget);

  Element? stable;
  Element? swapper;
  bool swapperIsOnTop = true;
  List<dynamic> insertSlots = <dynamic>[];
  List<Pair<dynamic>> moveSlots = <Pair<dynamic>>[];
  List<dynamic> removeSlots = <dynamic>[];

  @override
  Swapper get widget => super.widget as Swapper;

  @override
  RenderSwapper get renderObject => super.renderObject as RenderSwapper;

  @override
  void visitChildren(ElementVisitor visitor) {
    if (stable != null)
      visitor(stable!);
    if (swapper != null)
      visitor(swapper!);
  }

  @override
  void update(Swapper newWidget) {
    super.update(newWidget);
    _updateChildren(newWidget);
  }

  @override
  void mount(Element? parent, Object? newSlot) {
    super.mount(parent, newSlot);
    _updateChildren(widget);
  }

  void _updateChildren(Swapper widget) {
    stable = updateChild(stable, widget.stable, 'stable');
    swapper = updateChild(swapper, widget.swapper, swapperIsOnTop);
    swapperIsOnTop = !swapperIsOnTop;
  }
}

class SwapperElementWithProperOverrides extends SwapperElement {
  SwapperElementWithProperOverrides(Swapper widget) : super(widget);

  @override
  void insertRenderObjectChild(RenderBox child, Object? slot) {
    insertSlots.add(slot);
    assert(child != null);
    if (slot == 'stable')
      renderObject.stable = child;
    else
      renderObject.setSwapper(child, slot! as bool);
  }

  @override
  void moveRenderObjectChild(RenderBox child, bool oldIsOnTop, bool newIsOnTop) {
    moveSlots.add(Pair<bool>(oldIsOnTop, newIsOnTop));
    assert(oldIsOnTop == !newIsOnTop);
    renderObject.setSwapper(child, newIsOnTop);
  }

  @override
  void removeRenderObjectChild(RenderBox child, Object? slot) {
    removeSlots.add(slot);
    if (slot == 'stable')
      renderObject.stable = null;
    else
      renderObject.setSwapper(null, slot! as bool);
  }
}

class SwapperElementWithNoOverrides extends SwapperElement {
  SwapperElementWithNoOverrides(Swapper widget) : super(widget);
}

class SwapperElementWithDeprecatedOverrides extends SwapperElement {
  SwapperElementWithDeprecatedOverrides(Swapper widget) : super(widget);

  @override
  // ignore: must_call_super
  void insertChildRenderObject(RenderBox child, Object? slot) {
    insertSlots.add(slot);
    assert(child != null);
    if (slot == 'stable')
      renderObject.stable = child;
    else
      renderObject.setSwapper(child, slot! as bool);
  }

  @override
  // ignore: must_call_super
  void moveChildRenderObject(RenderBox child, bool isOnTop) {
    moveSlots.add(Pair<bool>(null, isOnTop));
    renderObject.setSwapper(child, isOnTop);
  }

  @override
  // ignore: must_call_super
  void removeChildRenderObject(RenderBox child) {
    removeSlots.add(null);
    if (child == renderObject._stable)
      renderObject.stable = null;
    else
      renderObject.setSwapper(null, swapperIsOnTop);
  }
}

class RenderSwapper extends RenderBox {
  RenderBox? _stable;
  RenderBox? get stable => _stable;
  set stable(RenderBox? child) {
    if (child == _stable)
      return;
    if (_stable != null)
      dropChild(_stable!);
    _stable = child;
    if (child != null)
      adoptChild(child);
  }

  bool? _swapperIsOnTop;
  RenderBox? _swapper;
  RenderBox? get swapper => _swapper;
  void setSwapper(RenderBox? child, bool isOnTop) {
    if (isOnTop != _swapperIsOnTop) {
      _swapperIsOnTop = isOnTop;
      markNeedsLayout();
    }
    if (child == _swapper)
      return;
    if (_swapper != null)
      dropChild(_swapper!);
    _swapper = child;
    if (child != null)
      adoptChild(child);
  }

  @override
  void visitChildren(RenderObjectVisitor visitor) {
    if (_stable != null)
      visitor(_stable!);
    if (_swapper != null)
      visitor(_swapper!);
  }

  @override
  void attach(PipelineOwner owner) {
    super.attach(owner);
    visitChildren((RenderObject child) => child.attach(owner));
  }

  @override
  void detach() {
    super.detach();
    visitChildren((RenderObject child) => child.detach());
  }

  @override
  Size computeDryLayout(BoxConstraints constraints) {
    return constraints.biggest;
  }

  @override
  void performLayout() {
    assert(constraints.hasBoundedWidth);
    assert(constraints.hasTightHeight);
    size = constraints.biggest;
    const Offset topOffset = Offset.zero;
    final Offset bottomOffset = Offset(0, size.height / 2);
    final BoxConstraints childConstraints = constraints.copyWith(
      minHeight: constraints.minHeight / 2,
      maxHeight: constraints.maxHeight / 2,
    );
    if (_stable != null) {
      final BoxParentData stableParentData = _stable!.parentData! as BoxParentData;
      _stable!.layout(childConstraints);
      stableParentData.offset = _swapperIsOnTop! ? bottomOffset : topOffset;
    }
    if (_swapper != null) {
      final BoxParentData swapperParentData = _swapper!.parentData! as BoxParentData;
      _swapper!.layout(childConstraints);
      swapperParentData.offset = _swapperIsOnTop! ? topOffset : bottomOffset;
    }
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    visitChildren((RenderObject child) {
      final BoxParentData childParentData = child.parentData! as BoxParentData;
      context.paintChild(child, offset + childParentData.offset);
    });
  }

  @override
  void redepthChildren() {
    visitChildren((RenderObject child) => redepthChild(child));
  }
}

BoxParentData parentDataFor(RenderObject renderObject) => renderObject.parentData! as BoxParentData;

void main() {
  testWidgets('RenderObjectElement *RenderObjectChild methods get called with correct arguments', (WidgetTester tester) async {
    const Key redKey = ValueKey<String>('red');
    const Key blueKey = ValueKey<String>('blue');
    Widget widget() {
      return SwapperWithProperOverrides(
        stable: ColoredBox(
          key: redKey,
          color: Color(nonconst(0xffff0000)),
        ),
        swapper: ColoredBox(
          key: blueKey,
          color: Color(nonconst(0xff0000ff)),
        ),
      );
    }

    await tester.pumpWidget(widget());
    final SwapperElement swapper = tester.element<SwapperElement>(find.byType(SwapperWithProperOverrides));
    final RenderBox redBox = tester.renderObject<RenderBox>(find.byKey(redKey));
    final RenderBox blueBox = tester.renderObject<RenderBox>(find.byKey(blueKey));
    expect(swapper.insertSlots.length, 2);
    expect(swapper.insertSlots, contains('stable'));
    expect(swapper.insertSlots, contains(true));
    expect(swapper.moveSlots, isEmpty);
    expect(swapper.removeSlots, isEmpty);
    expect(parentDataFor(redBox).offset, const Offset(0, 300));
    expect(parentDataFor(blueBox).offset, Offset.zero);
    await tester.pumpWidget(widget());
    expect(swapper.insertSlots.length, 2);
    expect(swapper.moveSlots.length, 1);
    expect(swapper.moveSlots, contains(const Pair<bool>(true, false)));
    expect(swapper.removeSlots, isEmpty);
    expect(parentDataFor(redBox).offset, Offset.zero);
    expect(parentDataFor(blueBox).offset, const Offset(0, 300));
    await tester.pumpWidget(const SwapperWithProperOverrides());
    expect(redBox.attached, false);
    expect(blueBox.attached, false);
    expect(swapper.insertSlots.length, 2);
    expect(swapper.moveSlots.length, 1);
    expect(swapper.removeSlots.length, 2);
    expect(swapper.removeSlots, contains('stable'));
    expect(swapper.removeSlots, contains(false));
  });

  testWidgets('RenderObjectElement *RenderObjectChild methods delegate to deprecated methods', (WidgetTester tester) async {
    const Key redKey = ValueKey<String>('red');
    const Key blueKey = ValueKey<String>('blue');
    Widget widget() {
      return SwapperWithDeprecatedOverrides(
        stable: ColoredBox(
          key: redKey,
          color: Color(nonconst(0xffff0000)),
        ),
        swapper: ColoredBox(
          key: blueKey,
          color: Color(nonconst(0xff0000ff)),
        ),
      );
    }

    await tester.pumpWidget(widget());
    final SwapperElement swapper = tester.element<SwapperElement>(find.byType(SwapperWithDeprecatedOverrides));
    final RenderBox redBox = tester.renderObject<RenderBox>(find.byKey(redKey));
    final RenderBox blueBox = tester.renderObject<RenderBox>(find.byKey(blueKey));
    expect(swapper.insertSlots.length, 2);
    expect(swapper.insertSlots, contains('stable'));
    expect(swapper.insertSlots, contains(true));
    expect(swapper.moveSlots, isEmpty);
    expect(swapper.removeSlots, isEmpty);
    expect(parentDataFor(redBox).offset, const Offset(0, 300));
    expect(parentDataFor(blueBox).offset, Offset.zero);
    await tester.pumpWidget(widget());
    expect(swapper.insertSlots.length, 2);
    expect(swapper.moveSlots.length, 1);
    expect(swapper.moveSlots, contains(const Pair<bool>(null, false)));
    expect(swapper.removeSlots, isEmpty);
    expect(parentDataFor(redBox).offset, Offset.zero);
    expect(parentDataFor(blueBox).offset, const Offset(0, 300));
    await tester.pumpWidget(const SwapperWithDeprecatedOverrides());
    expect(redBox.attached, false);
    expect(blueBox.attached, false);
    expect(swapper.insertSlots.length, 2);
    expect(swapper.moveSlots.length, 1);
    expect(swapper.removeSlots.length, 2);
    expect(swapper.removeSlots, <bool?>[null,null]);
  });

  testWidgets('RenderObjectElement *ChildRenderObject methods fail with deprecation message', (WidgetTester tester) async {
    const Key redKey = ValueKey<String>('red');
    const Key blueKey = ValueKey<String>('blue');
    Widget widget() {
      return SwapperWithNoOverrides(
        stable: ColoredBox(
          key: redKey,
          color: Color(nonconst(0xffff0000)),
        ),
        swapper: ColoredBox(
          key: blueKey,
          color: Color(nonconst(0xff0000ff)),
        ),
      );
    }

    await tester.pumpWidget(widget());
    final FlutterError error = tester.takeException() as FlutterError;
    final ErrorSummary summary = error.diagnostics.first as ErrorSummary;
    expect(summary.toString(), contains('deprecated'));
  });
}
