// 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:material_ui/material_ui.dart';

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

RenderBoxToRenderSectorAdapter initCircle() {
  return RenderBoxToRenderSectorAdapter(innerRadius: 25.0, child: RenderSectorRing());
}

class SectorApp extends StatefulWidget {
  const SectorApp({super.key});

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

class SectorAppState extends State<SectorApp> {
  final RenderBoxToRenderSectorAdapter sectors = initCircle();
  final math.Random rand = math.Random(1);

  List<double> wantedSectorSizes = <double>[];
  List<double> actualSectorSizes = <double>[];
  double get currentTheta =>
      wantedSectorSizes.fold<double>(0.0, (double total, double value) => total + value);

  void addSector() {
    final double currentTheta = this.currentTheta;
    if (currentTheta < kTwoPi) {
      double deltaTheta;
      if (currentTheta >= kTwoPi - (math.pi * 0.2 + 0.05)) {
        deltaTheta = kTwoPi - currentTheta;
      } else {
        deltaTheta = math.pi * rand.nextDouble() / 5.0 + 0.05;
      }
      wantedSectorSizes.add(deltaTheta);
      updateEnabledState();
    }
  }

  void removeSector() {
    if (wantedSectorSizes.isNotEmpty) {
      wantedSectorSizes.removeLast();
      updateEnabledState();
    }
  }

  void doUpdates() {
    var index = 0;
    while (index < actualSectorSizes.length &&
        index < wantedSectorSizes.length &&
        actualSectorSizes[index] == wantedSectorSizes[index]) {
      index += 1;
    }
    final ring = sectors.child! as RenderSectorRing;
    while (index < actualSectorSizes.length) {
      ring.remove(ring.lastChild!);
      actualSectorSizes.removeLast();
    }
    while (index < wantedSectorSizes.length) {
      final color = Color(((0xFF << 24) + rand.nextInt(0xFFFFFF)) | 0x808080);
      ring.add(RenderSolidColor(color, desiredDeltaTheta: wantedSectorSizes[index]));
      actualSectorSizes.add(wantedSectorSizes[index]);
      index += 1;
    }
  }

  static RenderBoxToRenderSectorAdapter initSector(Color color) {
    final ring = RenderSectorRing(padding: 1.0);
    ring.add(RenderSolidColor(const Color(0xFF909090), desiredDeltaTheta: kTwoPi * 0.15));
    ring.add(RenderSolidColor(const Color(0xFF909090), desiredDeltaTheta: kTwoPi * 0.15));
    ring.add(RenderSolidColor(color, desiredDeltaTheta: kTwoPi * 0.2));
    return RenderBoxToRenderSectorAdapter(innerRadius: 5.0, child: ring);
  }

  RenderBoxToRenderSectorAdapter sectorAddIcon = initSector(const Color(0xFF00DD00));
  RenderBoxToRenderSectorAdapter sectorRemoveIcon = initSector(const Color(0xFFDD0000));

  bool _enabledAdd = true;
  bool _enabledRemove = false;
  void updateEnabledState() {
    setState(() {
      _enabledAdd = currentTheta < kTwoPi;
      _enabledRemove = wantedSectorSizes.isNotEmpty;
    });
  }

  void recursivelyDisposeChildren(RenderObject parent) {
    parent.visitChildren((RenderObject child) {
      recursivelyDisposeChildren(child);
      child.dispose();
    });
  }

  Widget buildBody() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        Container(
          padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 25.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              ElevatedButton(
                onPressed: _enabledAdd ? addSector : null,
                child: IntrinsicWidth(
                  child: Row(
                    children: <Widget>[
                      Container(
                        padding: const EdgeInsets.all(4.0),
                        margin: const EdgeInsets.only(right: 10.0),
                        child: WidgetToRenderBoxAdapter(
                          renderBox: sectorAddIcon,
                          onUnmount: () {
                            recursivelyDisposeChildren(sectorAddIcon);
                          },
                        ),
                      ),
                      const Text('ADD SECTOR'),
                    ],
                  ),
                ),
              ),
              ElevatedButton(
                onPressed: _enabledRemove ? removeSector : null,
                child: IntrinsicWidth(
                  child: Row(
                    children: <Widget>[
                      Container(
                        padding: const EdgeInsets.all(4.0),
                        margin: const EdgeInsets.only(right: 10.0),
                        child: WidgetToRenderBoxAdapter(
                          renderBox: sectorRemoveIcon,
                          onUnmount: () {
                            recursivelyDisposeChildren(sectorRemoveIcon);
                          },
                        ),
                      ),
                      const Text('REMOVE SECTOR'),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
        Expanded(
          child: Container(
            margin: const EdgeInsets.all(8.0),
            decoration: BoxDecoration(border: Border.all()),
            padding: const EdgeInsets.all(8.0),
            child: WidgetToRenderBoxAdapter(
              renderBox: sectors,
              onBuild: doUpdates,
              onUnmount: () {
                recursivelyDisposeChildren(sectors);
              },
            ),
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Sector Layout',
      home: Scaffold(
        appBar: AppBar(title: const Text('Sector Layout in a Widget Tree')),
        body: buildBody(),
      ),
    );
  }
}

void main() {
  runApp(const SectorApp());
}
