// Copyright 2021 The Flutter team. 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 '../../../../../shared/utils/app_scroll_behavior.dart';
import 'constants.dart';

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

  @override
  Widget build(BuildContext context) {
    final EdgeInsets padding = MediaQuery.paddingOf(context);
    final ThemeData theme = Theme.of(context);
    final Color shadowColor = theme.colorScheme.shadow;
    final Color surfaceTint = theme.colorScheme.primary;
    return ScrollConfiguration(
      behavior: const DragScrollBehavior(),
      child: Expanded(
        child: CustomScrollView(
          slivers: <Widget>[
            SliverToBoxAdapter(
              child: Padding(
                padding: EdgeInsets.fromLTRB(16.0, 20 + padding.top, 16.0, 0),
                child: Text(
                  'Surface Tint Color Only',
                  style: theme.textTheme.titleLarge,
                ),
              ),
            ),
            ElevationGrid(
              surfaceTintColor: surfaceTint,
              shadowColor: theme.useMaterial3 ? Colors.transparent : null,
            ),
            SliverList(
              delegate: SliverChildListDelegate(<Widget>[
                const SizedBox(height: 10),
                Padding(
                  padding: const EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 0),
                  child: Text(
                    'Surface Tint Color and Shadow Color',
                    style: theme.textTheme.titleLarge,
                  ),
                ),
              ]),
            ),
            ElevationGrid(
              shadowColor: shadowColor,
              surfaceTintColor: surfaceTint,
            ),
            SliverList(
              delegate: SliverChildListDelegate(<Widget>[
                const SizedBox(height: 10),
                Padding(
                  padding: const EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 0),
                  child: Text(
                    'Shadow Color Only',
                    style: theme.textTheme.titleLarge,
                  ),
                ),
              ]),
            ),
            ElevationGrid(shadowColor: shadowColor),
            SliverPadding(padding: EdgeInsets.only(bottom: padding.bottom)),
          ],
        ),
      ),
    );
  }
}

class ElevationGrid extends StatelessWidget {
  const ElevationGrid({super.key, this.shadowColor, this.surfaceTintColor});

  final Color? shadowColor;
  final Color? surfaceTintColor;

  List<ElevationCard> elevationCards(
      Color? shadowColor, Color? surfaceTintColor) {
    return elevations
        .map(
          (ElevationInfo elevationInfo) => ElevationCard(
            info: elevationInfo,
            shadowColor: shadowColor,
            surfaceTint: surfaceTintColor,
          ),
        )
        .toList();
  }

  @override
  Widget build(BuildContext context) {
    return SliverPadding(
      padding: const EdgeInsets.all(8),
      sliver: SliverLayoutBuilder(
          builder: (BuildContext context, SliverConstraints constraints) {
        if (constraints.crossAxisExtent < kNarrowScreenWidthThreshold) {
          return SliverGrid.count(
            crossAxisCount: 3,
            children: elevationCards(shadowColor, surfaceTintColor),
          );
        } else {
          return SliverGrid.count(
            crossAxisCount: 6,
            children: elevationCards(shadowColor, surfaceTintColor),
          );
        }
      }),
    );
  }
}

class ElevationCard extends StatefulWidget {
  const ElevationCard(
      {super.key, required this.info, this.shadowColor, this.surfaceTint});

  final ElevationInfo info;
  final Color? shadowColor;
  final Color? surfaceTint;

  @override
  State<ElevationCard> createState() => _ElevationCardState();
}

class _ElevationCardState extends State<ElevationCard> {
  late double _elevation;

  @override
  void initState() {
    super.initState();
    _elevation = widget.info.elevation;
  }

  @override
  Widget build(BuildContext context) {
    const BorderRadius borderRadius = BorderRadius.all(Radius.circular(4.0));
    final ThemeData theme = Theme.of(context);
    final Color color = theme.colorScheme.surface;

    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Material(
        borderRadius: borderRadius,
        elevation: _elevation,
        color: color,
        shadowColor: widget.shadowColor,
        surfaceTintColor: widget.surfaceTint,
        type: MaterialType.card,
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Text(
                'Level ${widget.info.level}',
                style: theme.textTheme.labelMedium,
              ),
              Text(
                '${widget.info.elevation.toStringAsFixed(0)} dp',
                style: theme.textTheme.labelMedium,
              ),
              if (widget.surfaceTint != null)
                Expanded(
                  child: Align(
                    alignment: Alignment.bottomRight,
                    child: Text(
                      '${widget.info.overlayPercent}%',
                      style: theme.textTheme.bodySmall,
                    ),
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }
}

class ElevationInfo {
  const ElevationInfo(this.level, this.elevation, this.overlayPercent);
  final int level;
  final double elevation;
  final int overlayPercent;
}

const List<ElevationInfo> elevations = <ElevationInfo>[
  ElevationInfo(0, 0.0, 0),
  ElevationInfo(1, 1.0, 5),
  ElevationInfo(2, 3.0, 8),
  ElevationInfo(3, 6.0, 11),
  ElevationInfo(4, 8.0, 12),
  ElevationInfo(5, 12.0, 14),
];
