// 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 'dart:async';

import 'package:wyatt_ui_components/wyatt_ui_components.dart';
import 'package:wyatt_ui_kit/src/components/buttons/cubit/button_cubit.dart';

class SelectableButtonCubit extends ButtonCubit {
  ButtonState _toggle(ButtonState state) {
    if (state.isSelected) {
      return state.copyWith(
        extraStates: state.extraStates
            .where((element) => element != ExtraState.selected)
            .toList(),
      );
    } else {
      return state.copyWith(
        extraStates: state.extraStates + [ExtraState.selected],
      );
    }
  }

  /// When the mouse is released on the button, the button will
  /// add the [ExtraState.selected] if it is selected, or remove
  /// the [ExtraState.selected] if it is not selected.
  ///
  /// If the button is disabled or freezed, this method does nothing.
  @override
  FutureOr<void> onClickUpIn() async {
    if (state.isDisabled || state.isFreezed) {
      return;
    }

    emit(_toggle(state).copyWith(state: ControlState.hovered));
  }

  @override
  FutureOr<void> onClickUpOut() async {
    if (state.isDisabled || state.isFreezed) {
      return;
    }

    emit(_toggle(state).copyWith(state: ControlState.normal));
  }

  /// When the button is selected. The button will add the
  /// [ExtraState.selected] to its extra states.
  ///
  /// Use this method to select the button programmatically.
  FutureOr<void> select() async {
    emit(
      state.copyWith(extraStates: state.extraStates + [ExtraState.selected]),
    );
  }

  /// When the button is unselected. The button will remove the
  /// [ExtraState.selected] from its extra states.
  ///
  /// Use this method to unselect the button programmatically.
  FutureOr<void> unselect() async {
    emit(
      state.copyWith(
        extraStates: state.extraStates
            .where((element) => element != ExtraState.selected)
            .toList(),
      ),
    );
  }
}
