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

import '../rendering/src/solid_color_box.dart';

// Solid color, RenderObject version
void addFlexChildSolidColor(RenderFlex parent, Color backgroundColor, {int flex = 0}) {
  final child = RenderSolidColorBox(backgroundColor);
  parent.add(child);
  final childParentData = child.parentData! as FlexParentData;
  childParentData.flex = flex;
}

// Solid color, Widget version
class Rectangle extends StatelessWidget {
  const Rectangle(this.color, {super.key});

  final Color color;

  @override
  Widget build(BuildContext context) {
    return Expanded(child: Container(color: color));
  }
}

double? value;
RenderObjectToWidgetElement<RenderBox>? element;
void attachWidgetTreeToRenderTree(RenderProxyBox container) {
  element = RenderObjectToWidgetAdapter<RenderBox>(
    container: container,
    child: Directionality(
      textDirection: TextDirection.ltr,
      child: SizedBox(
        height: 300.0,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: <Widget>[
            const Rectangle(Color(0xFF00FFFF)),
            Material(
              child: Container(
                padding: const EdgeInsets.all(10.0),
                margin: const EdgeInsets.all(10.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: <Widget>[
                    ElevatedButton(
                      child: const Row(children: <Widget>[FlutterLogo(), Text('PRESS ME')]),
                      onPressed: () {
                        value = value == null ? 0.1 : (value! + 0.1) % 1.0;
                        attachWidgetTreeToRenderTree(container);
                      },
                    ),
                    CircularProgressIndicator(value: value),
                  ],
                ),
              ),
            ),
            const Rectangle(Color(0xFFFFFF00)),
          ],
        ),
      ),
    ),
  ).attachToRenderTree(WidgetsBinding.instance.buildOwner!, element);
}

Duration? timeBase;
late RenderTransform transformBox;

void rotate(Duration timeStamp) {
  timeBase ??= timeStamp;
  final double delta =
      (timeStamp - timeBase!).inMicroseconds.toDouble() / Duration.microsecondsPerSecond; // radians

  transformBox.setIdentity();
  transformBox.rotateZ(delta);

  WidgetsBinding.instance.buildOwner!.buildScope(element!);
}

void main() {
  final WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
  final proxy = RenderProxyBox();
  attachWidgetTreeToRenderTree(proxy);

  final flexRoot = RenderFlex(direction: Axis.vertical);
  addFlexChildSolidColor(flexRoot, const Color(0xFFFF00FF), flex: 1);
  flexRoot.add(proxy);
  addFlexChildSolidColor(flexRoot, const Color(0xFF0000FF), flex: 1);

  transformBox = RenderTransform(
    child: flexRoot,
    transform: Matrix4.identity(),
    alignment: Alignment.center,
  );
  final root = RenderPadding(padding: const EdgeInsets.all(80.0), child: transformBox);

  // TODO(goderbauer): Create a window if embedder doesn't provide an implicit view to draw into.
  assert(binding.platformDispatcher.implicitView != null);
  final view = RenderView(view: binding.platformDispatcher.implicitView!, child: root);
  final pipelineOwner = PipelineOwner()..rootNode = view;
  binding.rootPipelineOwner.adoptChild(pipelineOwner);
  binding.addRenderView(view);
  view.prepareInitialFrame();

  binding.addPersistentFrameCallback(rotate);
}
