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

/// Flutter code sample for [ColorScheme.fromImageProvider] with content-based dynamic color.

const Widget divider = SizedBox(height: 10);
const double narrowScreenWidthThreshold = 400;

void main() => runApp(DynamicColorExample());

class DynamicColorExample extends StatefulWidget {
  DynamicColorExample({super.key});

  final List<ImageProvider> images = <NetworkImage>[
    const NetworkImage(
        'https://flutter.github.io/assets-for-api-docs/assets/material/content_based_color_scheme_1.png'),
    const NetworkImage(
        'https://flutter.github.io/assets-for-api-docs/assets/material/content_based_color_scheme_2.png'),
    const NetworkImage(
        'https://flutter.github.io/assets-for-api-docs/assets/material/content_based_color_scheme_3.png'),
    const NetworkImage(
        'https://flutter.github.io/assets-for-api-docs/assets/material/content_based_color_scheme_4.png'),
    const NetworkImage(
        'https://flutter.github.io/assets-for-api-docs/assets/material/content_based_color_scheme_5.png'),
    const NetworkImage(
        'https://flutter.github.io/assets-for-api-docs/assets/material/content_based_color_scheme_6.png'),
  ];

  @override
  State<DynamicColorExample> createState() => _DynamicColorExampleState();
}

class _DynamicColorExampleState extends State<DynamicColorExample> {
  late ColorScheme currentColorScheme;
  String currentHyperlinkImage = '';
  late int selectedImage;
  late bool isLight;
  late bool isLoading;

  @override
  void initState() {
    super.initState();
    selectedImage = 0;
    isLight = true;
    isLoading = true;
    currentColorScheme = const ColorScheme.light();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _updateImage(widget.images[selectedImage]);
      isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    final ColorScheme colorScheme = currentColorScheme;
    final Color selectedColor = currentColorScheme.primary;

    final ThemeData lightTheme = ThemeData(
      colorSchemeSeed: selectedColor,
      brightness: Brightness.light,
      useMaterial3: false,
    );
    final ThemeData darkTheme = ThemeData(
      colorSchemeSeed: selectedColor,
      brightness: Brightness.dark,
      useMaterial3: false,
    );

    Widget schemeLabel(String brightness, ColorScheme colorScheme) {
      return Padding(
        padding: const EdgeInsets.symmetric(vertical: 15),
        child: Text(
          brightness,
          style: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.onSecondaryContainer),
        ),
      );
    }

    Widget schemeView(ThemeData theme) {
      return Padding(
        padding: const EdgeInsets.symmetric(horizontal: 15),
        child: ColorSchemeView(colorScheme: theme.colorScheme),
      );
    }

    return MaterialApp(
      theme: ThemeData(useMaterial3: true, colorScheme: colorScheme),
      debugShowCheckedModeBanner: false,
      home: Builder(
        builder: (BuildContext context) => Scaffold(
          appBar: AppBar(
            title: const Text('Content Based Dynamic Color'),
            backgroundColor: colorScheme.primary,
            foregroundColor: colorScheme.onPrimary,
            actions: <Widget>[
              const Icon(Icons.light_mode),
              Switch(
                  activeColor: colorScheme.primary,
                  activeTrackColor: colorScheme.surface,
                  inactiveTrackColor: colorScheme.onSecondary,
                  value: isLight,
                  onChanged: (bool value) {
                    setState(() {
                      isLight = value;
                      _updateImage(widget.images[selectedImage]);
                    });
                  })
            ],
          ),
          body: Center(
            child: isLoading
                ? const CircularProgressIndicator()
                : ColoredBox(
                    color: colorScheme.secondaryContainer,
                    child: Column(
                      children: <Widget>[
                        divider,
                        _imagesRow(
                          context,
                          widget.images,
                          colorScheme,
                        ),
                        divider,
                        Expanded(
                          child: ColoredBox(
                            color: colorScheme.surface,
                            child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
                              if (constraints.maxWidth < narrowScreenWidthThreshold) {
                                return SingleChildScrollView(
                                  child: Column(
                                    children: <Widget>[
                                      divider,
                                      schemeLabel('Light ColorScheme', colorScheme),
                                      schemeView(lightTheme),
                                      divider,
                                      divider,
                                      schemeLabel('Dark ColorScheme', colorScheme),
                                      schemeView(darkTheme),
                                    ],
                                  ),
                                );
                              } else {
                                return SingleChildScrollView(
                                  child: Padding(
                                    padding: const EdgeInsets.only(top: 5),
                                    child: Column(
                                      children: <Widget>[
                                        Row(
                                          children: <Widget>[
                                            Expanded(
                                              child: Column(
                                                children: <Widget>[
                                                  schemeLabel('Light ColorScheme', colorScheme),
                                                  schemeView(lightTheme),
                                                ],
                                              ),
                                            ),
                                            Expanded(
                                              child: Column(
                                                children: <Widget>[
                                                  schemeLabel('Dark ColorScheme', colorScheme),
                                                  schemeView(darkTheme),
                                                ],
                                              ),
                                            ),
                                          ],
                                        ),
                                      ],
                                    ),
                                  ),
                                );
                              }
                            }),
                          ),
                        ),
                      ],
                    ),
                  ),
          ),
        ),
      ),
    );
  }

  Future<void> _updateImage(ImageProvider provider) async {
    final ColorScheme newColorScheme = await ColorScheme.fromImageProvider(
        provider: provider, brightness: isLight ? Brightness.light : Brightness.dark);
    if (!mounted) {
      return;
    }
    setState(() {
      selectedImage = widget.images.indexOf(provider);
      currentColorScheme = newColorScheme;
    });
  }

  // For small screens, have two rows of image selection. For wide screens,
  // fit them onto one row.
  Widget _imagesRow(BuildContext context, List<ImageProvider> images, ColorScheme colorScheme) {
    final double windowHeight = MediaQuery.of(context).size.height;
    final double windowWidth = MediaQuery.of(context).size.width;
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
        if (constraints.maxWidth > 800) {
          return _adaptiveLayoutImagesRow(images, colorScheme, windowHeight);
        } else {
          return Column(children: <Widget>[
            _adaptiveLayoutImagesRow(images.sublist(0, 3), colorScheme, windowWidth),
            _adaptiveLayoutImagesRow(images.sublist(3), colorScheme, windowWidth),
          ]);
        }
      }),
    );
  }

  Widget _adaptiveLayoutImagesRow(List<ImageProvider> images, ColorScheme colorScheme, double windowWidth) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: images
          .map(
            (ImageProvider image) => Flexible(
              flex: (images.length / 3).floor(),
              child: GestureDetector(
                onTap: () => _updateImage(image),
                child: Card(
                  color: widget.images.indexOf(image) == selectedImage
                      ? colorScheme.primaryContainer
                      : colorScheme.surface,
                  child: Padding(
                    padding: const EdgeInsets.all(5.0),
                    child: ConstrainedBox(
                      constraints: BoxConstraints(maxWidth: windowWidth * .25),
                      child: ClipRRect(
                        borderRadius: BorderRadius.circular(8.0),
                        child: Image(image: image),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          )
          .toList(),
    );
  }
}

class ColorSchemeView extends StatelessWidget {
  const ColorSchemeView({super.key, required this.colorScheme});

  final ColorScheme colorScheme;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        ColorGroup(children: <ColorChip>[
          ColorChip(label: 'primary', color: colorScheme.primary, onColor: colorScheme.onPrimary),
          ColorChip(label: 'onPrimary', color: colorScheme.onPrimary, onColor: colorScheme.primary),
          ColorChip(
              label: 'primaryContainer', color: colorScheme.primaryContainer, onColor: colorScheme.onPrimaryContainer),
          ColorChip(
              label: 'onPrimaryContainer',
              color: colorScheme.onPrimaryContainer,
              onColor: colorScheme.primaryContainer),
        ]),
        divider,
        ColorGroup(children: <ColorChip>[
          ColorChip(label: 'secondary', color: colorScheme.secondary, onColor: colorScheme.onSecondary),
          ColorChip(label: 'onSecondary', color: colorScheme.onSecondary, onColor: colorScheme.secondary),
          ColorChip(
              label: 'secondaryContainer',
              color: colorScheme.secondaryContainer,
              onColor: colorScheme.onSecondaryContainer),
          ColorChip(
              label: 'onSecondaryContainer',
              color: colorScheme.onSecondaryContainer,
              onColor: colorScheme.secondaryContainer),
        ]),
        divider,
        ColorGroup(
          children: <ColorChip>[
            ColorChip(label: 'tertiary', color: colorScheme.tertiary, onColor: colorScheme.onTertiary),
            ColorChip(label: 'onTertiary', color: colorScheme.onTertiary, onColor: colorScheme.tertiary),
            ColorChip(
                label: 'tertiaryContainer',
                color: colorScheme.tertiaryContainer,
                onColor: colorScheme.onTertiaryContainer),
            ColorChip(
                label: 'onTertiaryContainer',
                color: colorScheme.onTertiaryContainer,
                onColor: colorScheme.tertiaryContainer),
          ],
        ),
        divider,
        ColorGroup(
          children: <ColorChip>[
            ColorChip(label: 'error', color: colorScheme.error, onColor: colorScheme.onError),
            ColorChip(label: 'onError', color: colorScheme.onError, onColor: colorScheme.error),
            ColorChip(
                label: 'errorContainer', color: colorScheme.errorContainer, onColor: colorScheme.onErrorContainer),
            ColorChip(
                label: 'onErrorContainer', color: colorScheme.onErrorContainer, onColor: colorScheme.errorContainer),
          ],
        ),
        divider,
        ColorGroup(
          children: <ColorChip>[
            ColorChip(label: 'surface', color: colorScheme.surface, onColor: colorScheme.onSurface),
            ColorChip(label: 'onSurface', color: colorScheme.onSurface, onColor: colorScheme.surface),
            ColorChip(
                label: 'onSurfaceVariant', color: colorScheme.onSurfaceVariant, onColor: colorScheme.surfaceContainerHighest),
          ],
        ),
        divider,
        ColorGroup(
          children: <ColorChip>[
            ColorChip(label: 'outline', color: colorScheme.outline),
            ColorChip(label: 'shadow', color: colorScheme.shadow),
            ColorChip(
                label: 'inverseSurface', color: colorScheme.inverseSurface, onColor: colorScheme.onInverseSurface),
            ColorChip(
                label: 'onInverseSurface', color: colorScheme.onInverseSurface, onColor: colorScheme.inverseSurface),
            ColorChip(label: 'inversePrimary', color: colorScheme.inversePrimary, onColor: colorScheme.primary),
          ],
        ),
      ],
    );
  }
}

class ColorGroup extends StatelessWidget {
  const ColorGroup({super.key, required this.children});

  final List<Widget> children;

  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
      child: Card(clipBehavior: Clip.antiAlias, child: Column(children: children)),
    );
  }
}

class ColorChip extends StatelessWidget {
  const ColorChip({
    super.key,
    required this.color,
    required this.label,
    this.onColor,
  });

  final Color color;
  final Color? onColor;
  final String label;

  static Color contrastColor(Color color) {
    final Brightness brightness = ThemeData.estimateBrightnessForColor(color);
    return switch (brightness) {
      Brightness.dark  => Colors.white,
      Brightness.light => Colors.black,
    };
  }

  @override
  Widget build(BuildContext context) {
    final Color labelColor = onColor ?? contrastColor(color);
    return ColoredBox(
      color: color,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          children: <Expanded>[
            Expanded(child: Text(label, style: TextStyle(color: labelColor))),
          ],
        ),
      ),
    );
  }
}
