// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import 'package:flutter/material.dart' hide ButtonStyle;
import 'package:flutter/services.dart';
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/state_listener.dart';
import 'package:wyatt_ui_kit/src/components/buttons/simple_icon_button/simple_icon_button_theme_resolver.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_box_border.dart';
import 'package:wyatt_ui_kit/src/components/gradients/gradient_icon.dart';
import 'package:wyatt_ui_kit/src/core/helpers/linear_gradient_helper.dart';

class SimpleIconButtonScreen extends CubitScreen<ButtonCubit, ButtonState> {
  const SimpleIconButtonScreen({
    this.icon,
    this.disabledStyle,
    this.normalStyle,
    this.hoveredStyle,
    this.focusedStyle,
    this.tappedStyle,
    this.onPressed,
    this.disabled,
    this.themeResolver,
    super.key,
  });

  final Icon? icon;

  final SimpleIconButtonStyle? disabledStyle;
  final SimpleIconButtonStyle? normalStyle;
  final SimpleIconButtonStyle? hoveredStyle;
  final SimpleIconButtonStyle? focusedStyle;
  final SimpleIconButtonStyle? tappedStyle;

  final void Function(ControlState state)? onPressed;
  final ValueNotifier<bool>? disabled;
  final SimpleIconButtonThemeResolver? themeResolver;

  @override
  ButtonCubit create(BuildContext context) => ButtonCubit();

  @override
  ButtonCubit init(BuildContext context, ButtonCubit bloc) {
    disabled?.addListener(() => StateListener.listen(disabled, bloc));

    /// Set the initial state depending on the disabled value
    /// after adding the listener.
    if (disabled?.value ?? false) {
      bloc.disable();
    }
    return bloc;
  }

  /// Negotiate the theme to get a complete style.
  SimpleIconButtonStyle _resolve(BuildContext context, ControlState state) {
    final SimpleIconButtonThemeResolver resolver = themeResolver ??
        SimpleIconButtonThemeResolver(
          customStyleFn: (context, {extra}) {
            switch (extra) {
              case ControlState.disabled:
                return disabledStyle;
              case ControlState.focused:
                return focusedStyle;
              case ControlState.hovered:
                return hoveredStyle;
              case ControlState.tapped:
                return tappedStyle;
              case ControlState.normal:
              case null:
                return normalStyle;
            }
          },
        );
    return resolver.negotiate(context, extra: state);
  }

  @override
  Widget onBuild(BuildContext context, ButtonState state) {
    final style = _resolve(context, state.state);

    return Focus(
      onFocusChange: (hasFocus) =>
          hasFocus ? bloc(context).onFocus() : bloc(context).onUnfocus(),
      onKeyEvent: (focusNode, event) {
        if (event.logicalKey == LogicalKeyboardKey.enter && state.isFocused) {
          onPressed?.call(state.state);
          bloc(context).onClickUpOut();
          return KeyEventResult.handled;
        }
        return KeyEventResult.ignored;
      },
      child: MouseRegion(
        cursor: SystemMouseCursors.click,
        onEnter: (event) {
          bloc(context).onMouseEnter();
        },
        onExit: (event) {
          bloc(context).onMouseLeave();
        },
        child: GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTapDown: (details) {
            bloc(context).onClickDown();
          },
          onTapUp: (details) {
            onPressed?.call(state.state);
            bloc(context).onClickUpIn();
          },
          onTapCancel: () {
            onPressed?.call(state.state);
            bloc(context).onClickUpOut();
          },
          child: SizedBox.square(
            dimension: style.dimension,
            child: AspectRatio(
              aspectRatio: 1,
              child: DecoratedBox(
                decoration: BoxDecoration(
                  color: style.backgroundColors?.color,
                  // If no border color => no default value
                  border: (style.borderColors != null && style.stroke != null)
                      ? (style.borderColors?.isGradient ?? false)
                          ? GradientBoxBorder(
                              gradient: LinearGradient(
                                colors: style.borderColors!.colors,
                              ),
                              width: style.stroke!,
                            )
                          : Border.all(
                              color: style.borderColors!.color,
                              width: style.stroke!,
                            )
                      : null,
                  // if no gradient colors => no default value
                  gradient: (style.backgroundColors?.isGradient ?? false)
                      ? LinearGradient(
                          colors: style.backgroundColors!.colors,
                        )
                      : null,
                  boxShadow: [
                    if (style.shadow != null) ...[style.shadow!]
                  ],
                  borderRadius: style.radius,
                ),
                child: ConstrainedBox(
                  constraints: BoxConstraints(
                    minWidth: style.dimension ?? 30,
                  ),
                  child: Padding(
                    padding: style.padding ?? EdgeInsets.zero,
                    child: Center(
                      /// Choose color
                      /// icon.color ??
                      ///  button.foregroundColors.colors ??
                      ///    buttonStyle.foregroundColors.colors ??
                      ///      context.buttonTheme.onPrimary
                      child: Builder(
                        builder: (context) {
                          if (icon?.color != null) {
                            return icon!;
                          }

                          if (!(style.foregroundColors?.isGradient ?? false)) {
                            return ColorFiltered(
                              colorFilter: ColorFilter.mode(
                                style.foregroundColors!.color,
                                BlendMode.srcIn,
                              ),
                              child: icon,
                            );
                          }

                          return icon!.toGradient(
                            LinearGradientHelper.fromMultiColor(
                              style.foregroundColors!,
                            ),
                          );
                        },
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
