import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:nut_player_example/src/common/models/option_data.dart';
import 'package:nut_player_example/src/common/repository/settings_repository.dart';
import 'package:nut_player_example/src/common/views/input_view.dart';
import 'package:nut_player_example/src/common/views/options_view.dart';
import 'package:nut_player_example/src/features/player_screen/domain/bloc/playerview_bloc.dart';
import 'package:nut_player_example/src/features/player_screen/presentation/player_button.dart';
import 'package:nut_player/nut_player.dart';
import 'package:nut_player_example/src/features/player_screen/presentation/player_custom_skin.dart';
import 'package:nut_player_example/src/features/player_screen/presentation/player_settings_view.dart';

class PlayerView extends StatefulWidget {
  const PlayerView({super.key});

  @override
  State<PlayerView> createState() => _PlayerViewState();
}

class _PlayerViewState extends State<PlayerView> {
  final TextEditingController _textController = TextEditingController();
  StreamSubscription<String>? _logSubscription;
  StreamSubscription<Object>? _skinActionsSubscription;
  late PlayerViewBloc _bloc;
  var _turns = 0;
  bool _isFullScreen = false;

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

    _bloc = context.read<PlayerViewBloc>();
    _logSubscription = _bloc.controller.logStream.listen((event) {
      final text = _textController.text;
      _textController.text = '$event\r\n$text';
    });

    _skinActionsSubscription = _bloc.controller.skinActionStream.listen((event) {
      final call = event as MethodCall;
      switch (call.method) {
        case 'pluginSkinDefaultAction':
          final fullscreen = call.arguments["onEnter"];
          final repository = context.read<SettingsRepository>();
          if (_isFullScreen != fullscreen &&
              repository.fullscreenSettings != RepositoryFullscreenSettings.off) {
            setState(() {
              _isFullScreen = fullscreen;

              if (fullscreen) {
                // В случае ландшафтного режима нам нужно сделать 3 поворота,
                // чтобы сделать ориентацию интерфейса как в ютубе.
                // Можно повернуть на 1, но тогда интерфейс не будет по тому же
                // краю, как в иосном демо-приложении
                _turns = repository.fullscreenSettings == RepositoryFullscreenSettings.landscape ? 3 : 0;
              } else {
                _turns = 0;
              }
            });
          }
        case 'pluginSkinSettingsAction':
          showCupertinoModalPopup(
            context: context,
            builder: (_) {
              final speedSettings = PlayerViewController.playbackSettings.firstWhere((element) => element.key == const Key('PlaybackSpeedSettingID'));
              final updatedSpeedSetting = _updatedSetting(speedSettings);

              var options = [updatedSpeedSetting];

              final qualitiesSettings = _createQualities(_bloc);
              if (qualitiesSettings != null) {
                final updatedQualitiesSettings = _updatedSetting(qualitiesSettings);
                options.add(updatedQualitiesSettings);
              }

              final subsSettings = _createSubs(_bloc);
              if (subsSettings != null) {
                final updatedSubsSettings = _updatedSetting(subsSettings);
                options.add(updatedSubsSettings);
              }

              return PlayerSettingsView(
                options: options,
                onChange: (option, key) {
                  switch (key) {
                    case const Key('PlaybackSpeedSettingID'):
                      _bloc.add(SpeedChangedEvent(option));
                      break;
                    case const Key('PlaybackSubsSettingID'):
                      _bloc.add(SubsChangedEvent(option));
                      break;
                    case const Key('PlaybackQualitySettingID'):
                      _bloc.add(QualityChangedEvent(option));
                      break;
                    default:
                      break;
                  }
                });
            }
          );
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    final videoPlayer = VideoPlayer(_bloc.controller);
    return _isFullScreen ? _makeFullscreenWidget(videoPlayer)
                         : _makePortraitWidget(videoPlayer);
  }

  @override
  void deactivate() {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp
    ]);
    _logSubscription?.cancel();
    _logSubscription = null;
    _skinActionsSubscription?.cancel();
    _skinActionsSubscription = null;

    final bloc = context.read<PlayerViewBloc>();
    bloc.controller.dispose();

    super.deactivate();
  }

  Widget _makePortraitWidget(VideoPlayer videoPlayer) {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp
    ]);
    return CupertinoPageScaffold(
        backgroundColor: CupertinoColors.extraLightBackgroundGray,
        navigationBar: CupertinoNavigationBar(
          key: const Key('PlayerAppBarID'),
          middle: const Text('Демо NutPlayer',
              style: TextStyle(
                  decoration: TextDecoration.none,
                  color: CupertinoColors.black,
                  fontWeight: FontWeight.w600)),
          leading: CupertinoNavigationBarBackButton(
              previousPageTitle: 'Назад',
              onPressed: () {
                _bloc.add(const DismissEvent());
              }),
          padding: const EdgeInsetsDirectional.all(0),
          backgroundColor: CupertinoColors.white,
        ),
        child: SafeArea(
          child: BlocBuilder<PlayerViewBloc, PlayerViewState>(
            builder: (context, state) {
              return Column(children: [
                AspectRatio(
                  aspectRatio: 16 / 10,
                  child: _buildPlayer(videoPlayer, context),
                ),
                const SizedBox(height: 10),
                Container(
                  margin: const EdgeInsets.symmetric(horizontal: 20),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      PlayerButton('Пуск', () {
                        _bloc.add(const PlayEvent());
                      }),
                      const SizedBox(width: 10),
                      PlayerButton('Пауза', () {
                        _bloc.add(const PauseEvent());
                      }),
                      const SizedBox(width: 10),
                      PlayerButton('Завершить', () {
                        _bloc.add(const EndEvent());
                      })
                    ],
                  ),
                ),

                Expanded(
                  child: ListView(
                    shrinkWrap: true,
                    children: [
                      CupertinoListSection.insetGrouped(
                          hasLeading: false,
                          header: Container(
                            margin: const EdgeInsets.only(top: 10),
                            padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 16),
                            child: Text('API Проигрывателя'.toUpperCase(),
                                style: const TextStyle(
                                    decoration: TextDecoration.none,
                                    color: CupertinoColors.systemGrey,
                                    fontSize: 13,
                                    fontWeight: FontWeight.w400)),
                          ),
                          children: _buildDynamicWidgets(PlayerViewController.playbackSettings, _bloc)
                      ),
                      CupertinoListSection.insetGrouped(
                          margin: const EdgeInsets.symmetric(vertical: 0, horizontal: 20),
                          hasLeading: false,
                          children:  _buildWidgets([PlayerViewController.startPosition], _bloc)
                      ),

                      if (context.read<SettingsRepository>().log != RepositoryLogType.off)
                          _buildLog()
                    ]
                  )
                )
              ]);
            },
          ),
        ));
  }

  Widget _buildLog() {
    return CupertinoListSection.insetGrouped(
        hasLeading: false,
        header: Container(
          margin: const EdgeInsets.only(top: 10),
          padding: const EdgeInsets.symmetric(horizontal: 16),
          child: Row(
            children: [
              Text('Лог плеера'.toUpperCase(),
                  style: const TextStyle(
                      decoration: TextDecoration.none,
                      color: CupertinoColors.systemGrey,
                      fontSize: 13,
                      fontWeight: FontWeight.w400)),
              const Spacer(),
              SizedBox(
                height: 25,
                child: CupertinoButton(
                    onPressed: () {
                      _textController.text = '';
                    },
                    padding: const EdgeInsets.all(0),
                    child: const Text('Очистить')),
              )
            ],
          ),
        ),
        children: <Widget>[
          CupertinoTextField(
            padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 18),
            decoration: const BoxDecoration(
              border: null,
              borderRadius: BorderRadius.all(Radius.circular(12)),
              color: CupertinoColors.white,
            ),
            minLines: 1,
            maxLines: 10,
            readOnly: true,
            maxLength: null,
            autocorrect: false,
            keyboardType: TextInputType.multiline,
            controller: _textController,
          ),
       ]
    );
  }

  List<Widget> _buildDynamicWidgets(List<Object> objects, PlayerViewBloc bloc) {
    var widgets = _buildWidgets(objects, bloc);

    final qualities = _createQualities(bloc);
    if (qualities != null) {
      final qualityWidget = _buildOptionsView(qualities, bloc);
      widgets.insert(1, qualityWidget);
    }
    
    final subtitles = _createSubs(bloc);
    if (subtitles != null) {
      final subtitleWidget = _buildOptionsView(subtitles, bloc);
      widgets.insert(2, subtitleWidget);
    }

    return widgets;
  }

  OptionDataContainer? _createQualities(PlayerViewBloc bloc) {
    final state = bloc.state;
    if (state is! PlayerViewController) { return null; }

    return PlayerViewController.createQualities(state.qualities);
  }

  OptionDataContainer? _createSubs(PlayerViewBloc bloc) {
    final state = bloc.state;
    if (state is! PlayerViewController) { return null; }

    return PlayerViewController.createSubs(state.subtitles);
  }
  
  OptionDataContainer _updatedSetting(OptionDataContainer oldValue) {
    return OptionDataContainer(
        key: oldValue.key,
        title: oldValue.title,
        options: oldValue.options,
        selectedIndex: _bloc.selectedIndex(oldValue),
        onSelectedOption: oldValue.onSelectedOption
    );
  }

  Widget _buildOptionsView(OptionDataContainer setting, PlayerViewBloc bloc) {
    final selectedIndex = bloc.selectedIndex(setting);
    return OptionsView(
        setting.title,
        setting.options,
        selectedIndex,
        (selectedIndex) {
          final selectedOption = setting.options[selectedIndex];
          final event = setting.onSelectedOption?.call(selectedOption);
          if (event != null) {
            bloc.add(event);
          }
        },
      key: setting.key
    );
  }

  List<Widget> _buildWidgets(List<Object> objects, PlayerViewBloc bloc) {
    return <Widget>[...objects.map((setting) {
      if (setting is OptionDataContainer) {
        return _buildOptionsView(setting, bloc);
      } else if (setting is NumericOptionData) {
        final currentValue = bloc.currentNumericValue(setting);
        return InputView(
          setting.title,
          currentValue, (newTime) {
            final event = setting.onChange?.call(newTime);
            if (event != null) {
              bloc.add(event);
            }
          }, key: setting.key,
        );
      } else {
        return const Text('not implemented');
      }
    }).toList()];
  }

  Widget _buildPlayer(VideoPlayer videoPlayer, BuildContext context) {
    List<Widget> widgets = [videoPlayer];
    final repository = context.read<SettingsRepository>();
    final isSkinByDefault = repository.isSkinByDefault;
    if (!isSkinByDefault) {
      widgets.add(_buildCustomSkin());
    }
    return isSkinByDefault ? videoPlayer : Stack(children: widgets);
  }

  Widget _buildCustomSkin() {
    return const PlayerCustomSkin();
  }

  Widget _makeFullscreenWidget(VideoPlayer videoPlayer) {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.landscapeRight,
    ]);
    final size = MediaQuery.of(context).size;
    return SafeArea(
      child:
        OrientationBuilder(
          builder: (context, orientation) {
            final repository = context.read<SettingsRepository>();
            switch (orientation) {
              case Orientation.portrait:
                // в случае режима .landscape нужно поворачивать на 90 градусов 2 раза,
                // т.к. 1 раз поворачивается сам экран + надо поворачивать
                // представление, чтобы проскочить свободное положение экрана.
                // Для .flexible не требуются дополнительные повороты, видео вращается вместе с экраном.
                _turns += repository.fullscreenSettings == RepositoryFullscreenSettings.flexible ? 0 : 2;
              case Orientation.landscape:
                // в случае ландшатного режима нам нужно компенсировать поворот
                // самого экрана, поэтому отнимаем один поворот на 90 градусов
                _turns += repository.fullscreenSettings == RepositoryFullscreenSettings.flexible ? 0 : -1;
            }
            return RotatedBox(
                quarterTurns: _turns,
                child: Container(
                  width: size.width,
                  height: size.height,
                  color: CupertinoColors.black,
                  child: videoPlayer,
                )
            );
          }
        )
    );
  }
}
