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

import '../../shared/color_scheme_box.dart';

/// Widget used to select used [FlexSurfaceMode] using a popup menu.
///
/// This is a stateless widget version of surface mode Popupmenu selection using
/// call back. It was designed this way to be state management agnostic.
/// Widget using this widget can use state management to get and set values
/// for this widget.
class SurfaceModePopupMenu extends StatelessWidget {
  const SurfaceModePopupMenu({
    super.key,
    required this.index,
    this.onChanged,
    this.title,
    this.subtitle,
    this.contentPadding,
    this.labelForDefault = 'default (null)',
    this.popupLabelDefault,
  });
  final int index;
  final ValueChanged<int>? onChanged;
  final Widget? title;
  final Widget? subtitle;
  final EdgeInsetsGeometry? contentPadding;
  final String labelForDefault;
  final String? popupLabelDefault;

  // A function that returns a List of widgets with the content that we
  // need in both the popup menu and toggle buttons implementation.
  // It needs the theme ColorScheme so it can't be a const list or final, and
  // we need to control when we only included a sub set in toggle buttons case.
  static List<Widget> getModeWidget(ColorScheme scheme,
          [bool allModes = true]) =>
      <Widget>[
        const Tooltip(
          message: 'Level blend\nAll at same level\n'
              '(level)',
          child: Icon(Icons.check_box_outline_blank),
        ),
        const Tooltip(
          message: 'Very high surfaces\nLow scaffold\n'
              '(highBackgroundLowScaffold)',
          child: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              Padding(
                padding: EdgeInsets.only(top: 10),
                child: Icon(Icons.layers_outlined),
              ),
              Icon(Icons.layers),
            ],
          ),
        ),
        const Tooltip(
          message: 'High surfaces\nLow scaffold\n'
              '(highSurfaceLowScaffold)',
          child: Icon(Icons.layers),
        ),
        const Tooltip(
          message: 'Low surfaces\nHigh scaffold\n'
              '(highScaffoldLowSurface)',
          child: Icon(Icons.layers_outlined),
        ),
        if (allModes)
          const Tooltip(
            message: 'Level surfaces\nHigh scaffold\n'
                '(highScaffoldLevelSurface)',
            child: Icon(Icons.dynamic_feed_rounded),
          ),
        const Tooltip(
          message: 'Level surfaces\nLow scaffold\n'
              '(levelSurfacesLowScaffold)',
          child:
              RotatedBox(quarterTurns: 2, child: Icon(Icons.horizontal_split)),
        ),
        const Tooltip(
          message: 'Low surfaces\nHigh scaffold\n'
              '(highScaffoldLowSurfaces)',
          child: Icon(Icons.horizontal_split),
        ),
        if (allModes)
          Tooltip(
            message: 'Level surfaces, low scaffold\n'
                'Level tertiaryContainer dialog\n'
                '(levelSurfacesLowScaffoldVariantDialog)',
            child: Stack(
              alignment: Alignment.center,
              children: <Widget>[
                const RotatedBox(
                    quarterTurns: 2, child: Icon(Icons.horizontal_split)),
                Icon(Icons.stop, color: scheme.tertiary, size: 18),
              ],
            ),
          ),
        if (allModes)
          Tooltip(
            message: 'Low surfaces, very high scaffold\n'
                'Low tertiaryContainer dialog\n'
                '(highScaffoldLowSurfacesVariantDialog)',
            child: Stack(
              alignment: Alignment.center,
              children: <Widget>[
                const Icon(Icons.horizontal_split),
                Icon(Icons.stop, color: scheme.tertiary, size: 18),
              ],
            ),
          ),
      ];

  // Short explanation of the used surface mode.
  static String modeShort(final FlexSurfaceMode mode) {
    switch (mode) {
      case FlexSurfaceMode.level:
        return 'Level blend\nAll at same level';
      case FlexSurfaceMode.highBackgroundLowScaffold:
        return 'Very high surfaces\nLow scaffold';
      case FlexSurfaceMode.highSurfaceLowScaffold:
        return 'High surfaces\nLow scaffold';
      case FlexSurfaceMode.highScaffoldLowSurface:
        return 'Low surfaces\nHigh scaffold';
      case FlexSurfaceMode.highScaffoldLevelSurface:
        return 'Level surfaces\nHigh scaffold';
      case FlexSurfaceMode.levelSurfacesLowScaffold:
        return 'Level surfaces\nLow scaffold';
      case FlexSurfaceMode.highScaffoldLowSurfaces:
        return 'Low surfaces\nHigh scaffold';
      case FlexSurfaceMode.levelSurfacesLowScaffoldVariantDialog:
        return 'Level surfaces, low scaffold\n'
            'Level tertContainer dialog';
      case FlexSurfaceMode.highScaffoldLowSurfacesVariantDialog:
        return 'Low surfaces, very hi scaffold\n'
            'Low tertContainer dialog';
      case FlexSurfaceMode.custom:
        return '';
    }
  }

  // Explain the used surface mode. This is for dev mode to have an explanation
  // of what the used surface mode. All of these are not used by out control,
  // but if we add them this will cover all of them.
  String explainMode(final FlexSurfaceMode mode) {
    switch (mode) {
      case FlexSurfaceMode.level:
        return 'Level blends\n'
            'Surfaces 1x  Scaffold 1x\n';
      case FlexSurfaceMode.highBackgroundLowScaffold:
        return 'Very high surfaces, low scaffold\n'
            'Surfaces 2x  Scaffold 1/2x\n';
      case FlexSurfaceMode.highSurfaceLowScaffold:
        return 'High surfaces, low scaffold\n'
            'Surface 3/2x  Scaffold 1/2x\n';
      case FlexSurfaceMode.highScaffoldLowSurface:
        return 'Low surfaces, high scaffold\n'
            'Surfaces 1/2x  Scaffold 3x\n';
      case FlexSurfaceMode.highScaffoldLevelSurface:
        return 'Level surfaces, high scaffold\n'
            'Surfaces 1x  Scaffold 3x\n';
      case FlexSurfaceMode.levelSurfacesLowScaffold:
        return 'Level surfaces, low scaffold\n'
            'Surfaces 1x  Scaffold 1/2x\n';
      case FlexSurfaceMode.highScaffoldLowSurfaces:
        return 'Low surfaces, high scaffold\n'
            'Surfaces 1/2x  Scaffold 3x\n';
      case FlexSurfaceMode.levelSurfacesLowScaffoldVariantDialog:
        return 'Level surfaces, low scaffold, level tertiary container dialog\n'
            'Surfaces 1x  Scaffold 1/2x\n'
            'Dialog 1x blend of tertiary container color';
      case FlexSurfaceMode.highScaffoldLowSurfacesVariantDialog:
        return 'Low surfaces, high scaffold, '
            'low tertiary container dialog\n'
            'Surfaces 1/2x  Scaffold 3x\n'
            'Dialog 1/2x blend of tertiary container color';
      case FlexSurfaceMode.custom:
        return '';
    }
  }

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    final ColorScheme scheme = theme.colorScheme;
    final TextStyle txtStyle = theme.textTheme.labelMedium!;
    final bool enabled = onChanged != null;
    final String styleName = explainMode(FlexSurfaceMode.values[index]);
    final List<Widget> modeWidgets = getModeWidget(scheme);

    final IconThemeData selectedIconTheme =
        theme.iconTheme.copyWith(color: scheme.onPrimary.withAlpha(0xE5));
    final IconThemeData unSelectedIconTheme =
        theme.iconTheme.copyWith(color: scheme.primary);

    return PopupMenuButton<int>(
      popUpAnimationStyle: AnimationStyle.noAnimation,
      position: PopupMenuPosition.under,
      offset: const Offset(0, -4),
      constraints: const BoxConstraints(maxHeight: 560),
      initialValue: index,
      tooltip: '',
      padding: EdgeInsets.zero,
      onSelected: (int index) {
        // We return -1 for index that reached max length or any negative
        // value will cause controller for a FlexAppBarStyle to be set to
        // "null", we need to be able to do that to input "null" property
        // value to FlexAppBarStyle configs.
        onChanged?.call(index);
      },
      enabled: enabled,
      itemBuilder: (BuildContext context) {
        return <PopupMenuItem<int>>[
          for (int i = 0; i < FlexSurfaceMode.values.length - 1; i++)
            PopupMenuItem<int>(
              value: i,
              child: ListTile(
                dense: true,
                contentPadding: EdgeInsets.zero,
                leading: index == i
                    ? IconTheme(
                        data: selectedIconTheme,
                        child: ColorSchemeBox(
                          backgroundColor: scheme.primary,
                          borderColor: scheme.primary,
                          child: modeWidgets[i],
                        ),
                      )
                    : IconTheme(
                        data: unSelectedIconTheme,
                        child: ColorSchemeBox(
                          backgroundColor: Colors.transparent,
                          borderColor: scheme.primary,
                          child: modeWidgets[i],
                        ),
                      ),
                title: Text(
                  modeShort(FlexSurfaceMode.values[i]),
                  style: txtStyle,
                ),
                subtitle: Text(
                  '(${FlexSurfaceMode.values[i].name})',
                  style: txtStyle.copyWith(fontSize: 9.0),
                ),
              ),
            )
        ];
      },
      child: ListTile(
        enabled: enabled,
        contentPadding: contentPadding,
        title: title,
        subtitle: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            if (subtitle != null) subtitle!,
            Text(styleName),
          ],
        ),
        trailing: Padding(
          padding: const EdgeInsetsDirectional.only(end: 5.0),
          child: IconTheme(
            data: selectedIconTheme,
            child: ColorSchemeBox(
              backgroundColor: scheme.primary,
              borderColor: scheme.primary,
              child: modeWidgets[index],
            ),
          ),
        ),
      ),
    );
  }
}
