part of 'control_board.dart';

class _ContrastToneBar extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _ContrastToneBarState();
}

class _ContrastToneBarState extends State<_ContrastToneBar> {
  final playerController = Get.find<IPlayerController>() as VidPlayerController;

  @override
  void initState() {
    WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      if (mounted) {
        playerController.eventHandler.addListener(onControllerEvent);
      }
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final processor = playerController.getProcessor<VidContrastProcessor>();
    return _ToneBar(
      max: 99,
      min: -99,
      value: processor?.contrast.toDouble() ?? 0.0,
      icon: const Icon(Icons.brightness_medium),
      onChange: (v) {
        playerController.setContrast(v.toInt());
      },
    );
  }

  @override
  void dispose() {
    playerController.eventHandler.removeListener(onControllerEvent);
    super.dispose();
  }

  void onControllerEvent(Object sender, VidPlayerEvent e) {
    if (e is VidPlayerContrastChangeEvent) {
      onPlayStatusChanged(e);
    }
  }

  void onPlayStatusChanged(VidPlayerContrastChangeEvent e) {
    setState(() {});
  }
}

class _BrightnessToneBar extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _BrightnessToneBarState();
}

class _BrightnessToneBarState extends State<_BrightnessToneBar> {
  final playerController = Get.find<IPlayerController>() as VidPlayerController;
  @override
  void initState() {
    WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      if (mounted) {
        playerController.eventHandler.addListener(onControllerEvent);
      }
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final processor = playerController.getProcessor<VidBrightnessProcessor>();
    return _ToneBar(
      max: 255,
      min: -255,
      value: processor?.brightness.toDouble() ?? 0.0,
      icon: const Icon(Icons.wb_sunny_sharp),
      onChange: (v) {
        playerController.setBrightness(v.toInt());
      },
    );
  }

  @override
  void dispose() {
    playerController.eventHandler.removeListener(onControllerEvent);
    super.dispose();
  }

  void onControllerEvent(Object sender, VidPlayerEvent e) {
    if (e is VidPlayerBrightnessChangeEvent) {
      onPlayStatusChanged(e);
    }
  }

  void onPlayStatusChanged(VidPlayerBrightnessChangeEvent e) {
    setState(() {});
  }
}

class _ToneBar extends StatefulWidget {
  const _ToneBar({
    Key? key,
    required this.icon,
    required this.min,
    required this.max,
    required this.value,
    this.onChange,
  }) : super(key: key);

  final Widget icon;
  final ValueChanged<double>? onChange;
  final double min;
  final double max;
  final double value;

  @override
  State<StatefulWidget> createState() => _ToneBarState();
}

class _ToneBarState extends State<_ToneBar> {
  static const _kIconSize = 20.0;
  static const splashRadius = _kIconSize / 2 + 3;

  late double _value;

  @override
  void initState() {
    syncProps();
    super.initState();
  }

  @override
  void didUpdateWidget(covariant _ToneBar oldWidget) {
    syncProps();
    super.didUpdateWidget(oldWidget);
  }

  void syncProps() {
    _value = widget.value;
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        const SizedBox(width: 8),
        widget.icon,
        const SizedBox(width: 8),
        buildReduceIcon(),
        buildSlider(context),
        buildIncreaseIcon(),
        const SizedBox(width: 8),
        Text('${_value.toInt()}'),
      ],
    );
  }

  Widget buildReduceIcon() {
    return IconButton(
      constraints: const BoxConstraints(
        minHeight: _kIconSize,
        minWidth: _kIconSize,
      ),
      splashRadius: splashRadius,
      padding: EdgeInsets.zero,
      onPressed: () {
        updateValue(_value - 1);
      },
      icon: const Icon(Icons.remove_circle_outline, size: _kIconSize),
    );
  }

  Widget buildIncreaseIcon() {
    return IconButton(
      constraints: const BoxConstraints(
        minHeight: _kIconSize,
        minWidth: _kIconSize,
      ),
      splashRadius: splashRadius,
      padding: EdgeInsets.zero,
      onPressed: () {
        updateValue(_value + 1);
      },
      icon: const Icon(Icons.add_circle_outline, size: _kIconSize),
    );
  }

  Widget buildSlider(BuildContext context) {
    final trackColor = Theme.of(context).primaryColor;
    return SliderTheme(
      data: SliderThemeData(
        trackHeight: 4,
        activeTrackColor: trackColor,
        inactiveTrackColor: trackColor,
        thumbColor: Colors.grey[300],
        thumbShape: const RoundSliderThumbShape(
          enabledThumbRadius: 6,
          elevation: 3.0,
        ),
        overlayShape: SliderComponentShape.noOverlay,
        trackShape: const _FullWidthRectangularSliderTrackShape(
          padding: EdgeInsets.symmetric(horizontal: 4),
        ),
      ),
      child: Slider(
        max: widget.max,
        min: widget.min,
        value: _value,
        label: _value.toInt().toString(),
        divisions: (widget.max - widget.min).toInt(),
        onChanged: (v) {
          updateValue(v);
        },
      ),
    );
  }

  void updateValue(double value) {
    setState(() {
      _value = value;
    });
    widget.onChange?.call(value);
  }
}

class _FullWidthRectangularSliderTrackShape
    extends RectangularSliderTrackShape {
  const _FullWidthRectangularSliderTrackShape({this.padding});

  final EdgeInsets? padding;

  @override
  Rect getPreferredRect({
    required RenderBox parentBox,
    Offset offset = Offset.zero,
    required SliderThemeData sliderTheme,
    bool isEnabled = false,
    bool isDiscrete = false,
  }) {
    double trackHeight = sliderTheme.trackHeight ?? 2;
    double trackLeft = offset.dx;
    double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
    // 让轨道宽度等于 Slider 宽度
    double trackWidth = parentBox.size.width;
    if (padding != null) {
      trackHeight -= padding!.bottom;
      trackHeight -= padding!.top;
      trackWidth -= padding!.right;
      trackWidth -= padding!.left;
      trackTop += padding!.top;
      trackLeft += padding!.left;
    }
    return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
  }
}
