// 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';

/// Flutter code sample for [GrowthDirection]s.

void main() => runApp(const ExampleApp());

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyWidget(),
    );
  }
}

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

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  final List<String> _alphabet = <String>[
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  ];
  final Widget _spacer = const SizedBox.square(dimension: 10);
  final UniqueKey _center = UniqueKey();
  AxisDirection _axisDirection = AxisDirection.down;

  Widget _getArrows(AxisDirection axisDirection) {
    final Widget arrow;
    switch (axisDirection) {
      case AxisDirection.up:
        arrow = const Icon(Icons.arrow_upward_rounded);
        return Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[arrow, arrow],
        );
      case AxisDirection.down:
        arrow = const Icon(Icons.arrow_downward_rounded);
        return Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[arrow, arrow],
        );
      case AxisDirection.left:
        arrow = const Icon(Icons.arrow_back_rounded);
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[arrow, arrow],
        );
      case AxisDirection.right:
        arrow = const Icon(Icons.arrow_forward_rounded);
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[arrow, arrow],
        );
    }
  }

  void _onAxisDirectionChanged(AxisDirection? axisDirection) {
    if (axisDirection != null && axisDirection != _axisDirection) {
      setState(() {
        // Respond to change in axis direction.
        _axisDirection = axisDirection;
      });
    }
  }

  Widget _getLeading(SliverConstraints constraints, bool isForward) {
    return Container(
      color: isForward ? Colors.orange[300] : Colors.green[400],
      padding: const EdgeInsets.all(8.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          Text(constraints.axis.toString()),
          _spacer,
          Text(constraints.axisDirection.toString()),
          _spacer,
          Text(constraints.growthDirection.toString()),
          _spacer,
          _getArrows(
            isForward
                ? _axisDirection
                // This method is available to conveniently flip an AxisDirection
                // into its opposite direction.
                : flipAxisDirection(_axisDirection),
          ),
        ],
      ),
    );
  }

  Widget _getRadioRow() {
    return DefaultTextStyle(
      style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
      child: RadioTheme(
        data: RadioThemeData(
          fillColor: MaterialStateProperty.all<Color>(Colors.white),
        ),
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              Radio<AxisDirection>(
                value: AxisDirection.up,
                groupValue: _axisDirection,
                onChanged: _onAxisDirectionChanged,
              ),
              const Text('up'),
              _spacer,
              Radio<AxisDirection>(
                value: AxisDirection.down,
                groupValue: _axisDirection,
                onChanged: _onAxisDirectionChanged,
              ),
              const Text('down'),
              _spacer,
              Radio<AxisDirection>(
                value: AxisDirection.left,
                groupValue: _axisDirection,
                onChanged: _onAxisDirectionChanged,
              ),
              const Text('left'),
              _spacer,
              Radio<AxisDirection>(
                value: AxisDirection.right,
                groupValue: _axisDirection,
                onChanged: _onAxisDirectionChanged,
              ),
              const Text('right'),
              _spacer,
            ],
          ),
        ),
      ),
    );
  }

  Widget _getList({required bool isForward}) {
    // The SliverLayoutBuilder is not necessary, and is here to allow us to see
    // the SliverConstraints & directional information that is provided to the
    // SliverList when laying out.
    return SliverLayoutBuilder(
      builder: (BuildContext context, SliverConstraints constraints) {
        return SliverList.builder(
          itemCount: 27,
          itemBuilder: (BuildContext context, int index) {
            final Widget child;
            if (index == 0) {
              child = _getLeading(constraints, isForward);
            } else {
              child = Container(
                color: isForward
                    ? (index.isEven ? Colors.amber[100] : Colors.amberAccent)
                    : (index.isEven ? Colors.green[100] : Colors.lightGreen),
                padding: const EdgeInsets.all(8.0),
                child: Center(child: Text(_alphabet[index - 1])),
              );
            }
            return Padding(
              padding: const EdgeInsets.all(8.0),
              child: child,
            );
          },
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('GrowthDirections'),
        bottom: PreferredSize(
          preferredSize: const Size.fromHeight(50),
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: _getRadioRow(),
          ),
        ),
      ),
      body: CustomScrollView(
        // This method is available to conveniently determine if an scroll
        // view is reversed by its AxisDirection.
        reverse: axisDirectionIsReversed(_axisDirection),
        // This method is available to conveniently convert an AxisDirection
        // into its Axis.
        scrollDirection: axisDirectionToAxis(_axisDirection),
        // Places the leading edge of the center sliver in the middle of the
        // viewport. Changing this value between 0.0 (the default) and 1.0
        // changes the position of the inflection point between GrowthDirections
        // in the viewport when the slivers are laid out.
        anchor: 0.5,
        center: _center,
        slivers: <Widget>[
          _getList(isForward: false),
          SliverToBoxAdapter(
            // This sliver will be located at the anchor. The scroll position
            // will progress in either direction from this point.
            key: _center,
            child: const Padding(
              padding: EdgeInsets.all(8.0),
              child: Center(child: Text('0', style: TextStyle(fontWeight: FontWeight.bold))),
            ),
          ),
          _getList(isForward: true),
        ],
      ),
    );
  }
}
