// 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/material.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());
}
