// 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.

// Flutter code sample for [GrowthDirection]s.

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

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

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

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      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),
        ],
      ),
    );
  }
}
