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

const Size _kTestViewSize = Size(800.0, 600.0);

class OffscreenRenderView extends RenderView {
  OffscreenRenderView() : super(
    configuration: const ViewConfiguration(size: _kTestViewSize),
    window: WidgetsBinding.instance.window,
  );

  @override
  void compositeFrame() {
    // Don't draw to ui.window
  }
}

class OffscreenWidgetTree {
  OffscreenWidgetTree() {
    renderView.attach(pipelineOwner);
    renderView.prepareInitialFrame();
    pipelineOwner.requestVisualUpdate();
  }

  final RenderView renderView = OffscreenRenderView();
  final BuildOwner buildOwner = BuildOwner();
  final PipelineOwner pipelineOwner = PipelineOwner();
  RenderObjectToWidgetElement<RenderBox> root;

  void pumpWidget(Widget app) {
    root = RenderObjectToWidgetAdapter<RenderBox>(
      container: renderView,
      debugShortDescription: '[root]',
      child: app,
    ).attachToRenderTree(buildOwner, root);
    pumpFrame();
  }

  void pumpFrame() {
    buildOwner.buildScope(root);
    pipelineOwner.flushLayout();
    pipelineOwner.flushCompositingBits();
    pipelineOwner.flushPaint();
    renderView.compositeFrame();
    pipelineOwner.flushSemantics();
    buildOwner.finalizeTree();
  }

}

class Counter {
  int count = 0;
}

class Trigger {
  VoidCallback callback;
  void fire() {
    if (callback != null)
      callback();
  }
}

class TriggerableWidget extends StatefulWidget {
  const TriggerableWidget({
    Key key,
    this.trigger,
    this.counter,
  }) : super(key: key);

  final Trigger trigger;
  final Counter counter;

  @override
  TriggerableState createState() => TriggerableState();
}

class TriggerableState extends State<TriggerableWidget> {
  @override
  void initState() {
    super.initState();
    widget.trigger.callback = fire;
  }

  @override
  void didUpdateWidget(TriggerableWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    widget.trigger.callback = fire;
  }

  int _count = 0;
  void fire() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    widget.counter.count++;
    return Text('Bang $_count!', textDirection: TextDirection.ltr);
  }
}

class TestFocusable extends StatefulWidget {
  const TestFocusable({
    Key key,
    this.focusNode,
    this.autofocus = true,
  }) : super(key: key);

  final bool autofocus;
  final FocusNode focusNode;

  @override
  TestFocusableState createState() => TestFocusableState();
}

class TestFocusableState extends State<TestFocusable> {
  bool _didAutofocus = false;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    if (!_didAutofocus && widget.autofocus) {
      _didAutofocus = true;
      FocusScope.of(context).autofocus(widget.focusNode);
    }
  }

  @override
  Widget build(BuildContext context) {
    return const Text('Test focus node', textDirection: TextDirection.ltr);
  }
}

void main() {
  testWidgets('no crosstalk between widget build owners', (WidgetTester tester) async {
    final Trigger trigger1 = Trigger();
    final Counter counter1 = Counter();
    final Trigger trigger2 = Trigger();
    final Counter counter2 = Counter();
    final OffscreenWidgetTree tree = OffscreenWidgetTree();
    // Both counts should start at zero
    expect(counter1.count, equals(0));
    expect(counter2.count, equals(0));
    // Lay out the "onscreen" in the default test binding
    await tester.pumpWidget(TriggerableWidget(trigger: trigger1, counter: counter1));
    // Only the "onscreen" widget should have built
    expect(counter1.count, equals(1));
    expect(counter2.count, equals(0));
    // Lay out the "offscreen" in a separate tree
    tree.pumpWidget(TriggerableWidget(trigger: trigger2, counter: counter2));
    // Now both widgets should have built
    expect(counter1.count, equals(1));
    expect(counter2.count, equals(1));
    // Mark both as needing layout
    trigger1.fire();
    trigger2.fire();
    // Marking as needing layout shouldn't immediately build anything
    expect(counter1.count, equals(1));
    expect(counter2.count, equals(1));
    // Pump the "onscreen" layout
    await tester.pump();
    // Only the "onscreen" widget should have rebuilt
    expect(counter1.count, equals(2));
    expect(counter2.count, equals(1));
    // Pump the "offscreen" layout
    tree.pumpFrame();
    // Now both widgets should have rebuilt
    expect(counter1.count, equals(2));
    expect(counter2.count, equals(2));
    // Mark both as needing layout, again
    trigger1.fire();
    trigger2.fire();
    // Now pump the "offscreen" layout first
    tree.pumpFrame();
    // Only the "offscreen" widget should have rebuilt
    expect(counter1.count, equals(2));
    expect(counter2.count, equals(3));
    // Pump the "onscreen" layout
    await tester.pump();
    // Now both widgets should have rebuilt
    expect(counter1.count, equals(3));
    expect(counter2.count, equals(3));
  });

  testWidgets('no crosstalk between focus nodes', (WidgetTester tester) async {
    final OffscreenWidgetTree tree = OffscreenWidgetTree();
    final FocusNode onscreenFocus = FocusNode();
    final FocusNode offscreenFocus = FocusNode();
    await tester.pumpWidget(
      TestFocusable(
        focusNode: onscreenFocus,
      ),
    );
    tree.pumpWidget(
      TestFocusable(
        focusNode: offscreenFocus,
      ),
    );

    // Autofocus is delayed one frame.
    await tester.pump();
    tree.pumpFrame();

    expect(onscreenFocus.hasFocus, isTrue);
    expect(offscreenFocus.hasFocus, isTrue);
  });

}
