import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:just_audio/just_audio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:share/share.dart';
import 'package:tangheem/api/tangheem_user_api_client.dart';
import 'package:tangheem/classes/colors.dart';
import 'package:tangheem/classes/consts.dart';
import 'package:tangheem/classes/utils.dart';
import 'package:tangheem/models/aya_tangheem_type_mapped.dart';

class AyaPlayerWidget extends StatefulWidget {
  final int surahNo;
  final int ayaNo;
  final String surahName;
  final String ayaTangheemTypeId;
  final GlobalKey globalKey;
  final List<VoiceNote> voiceNoteList;

  AyaPlayerWidget({Key key, this.surahName, this.ayaTangheemTypeId, this.voiceNoteList, this.ayaNo, this.surahNo, @required this.globalKey}) : super(key: key);

  @override
  _AyaPlayerWidgetState createState() {
    return _AyaPlayerWidgetState();
  }
}

class _AyaPlayerWidgetState extends State<AyaPlayerWidget> {
  double sliderValue = 0.4;
  bool isPlaying = false;
  AudioPlayer _player;
  bool _isAudioHaveError = false;

  @override
  void initState() {
    super.initState();
    _player = AudioPlayer();
    setAudioSource();
  }

  setAudioSource() {
    try {
      List<AudioSource> voiceList = [];

      if ((widget.voiceNoteList?.length ?? 0) > 0) {
        voiceList = widget.voiceNoteList.map((e) => AudioSource.uri(Uri.parse(ApiConsts.baseUrl + e.exposeFilePath))).toList();
      }

      final _playlist = ConcatenatingAudioSource(children: voiceList);
      _player.setAudioSource(_playlist, initialIndex: 0, initialPosition: Duration.zero).then((value) => () {});
    } catch (e) {
      _isAudioHaveError = true;
    }
  }

  @override
  void didUpdateWidget(covariant AyaPlayerWidget oldWidget) {
    if (widget.voiceNoteList != oldWidget.voiceNoteList) {
      setAudioSource();
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    _player.dispose();
    super.dispose();
  }

  int _tempIndex;
  Uint8List temp;

  // made this dedicated function to remove avatar flashing
  DecorationImage getDecodedImage(int index) {
    if (_tempIndex == null || _tempIndex != index) {
      _tempIndex = index;
      String encodedImage = widget.voiceNoteList.elementAt(index).profilePicture;
      if (encodedImage?.contains("data:image/png;base64,") ?? false) {
        encodedImage = encodedImage.replaceAll("data:image/png;base64,", "");
      }    if (encodedImage == null) return null;
      temp = base64Decode(encodedImage);
    }
    if (temp == null) return null;
    return DecorationImage(
      fit: BoxFit.cover,
      image: MemoryImage(temp),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: 8, bottom: 8),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(8),
      ),
      padding: EdgeInsets.all(8),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Row(
            children: [
              if (widget.voiceNoteList.length > 1)
                PopupMenuButton(
                  padding: EdgeInsets.fromLTRB(4, 4, 0, 4),
                  onSelected: (int index) {
                    _player.seek(Duration.zero, index: index);
                  },
                  child: Transform.rotate(
                    angle: 180 * math.pi / 180,
                    child: SvgPicture.asset(
                      "assets/icons/drop_menu.svg",
                      width: 16,
                    ),
                  ),
                  itemBuilder: (context) {
                    var _voiceList = widget.voiceNoteList;
                    var length = _voiceList.length < 2 ? 0 : _voiceList.length;

                    return List.generate(length, (index) {
                      return PopupMenuItem(
                        value: index,
                        child: Text(
                          '${_voiceList[index].userName}',
                          style: TextStyle(color: ColorConsts.primaryBlack),
                        ),
                      );
                    });
                  },
                ),
              if ((widget.voiceNoteList?.length ?? 0) > 0)
                StreamBuilder<int>(
                  stream: _player.currentIndexStream,
                  builder: (context, snapshot) {
                    int state = snapshot.data;
                    if (state == null) return SizedBox();
                    return Container(
                      width: 50.0,
                      margin: EdgeInsets.only(left: 8, right: 8),
                      height: 50.0,
                      decoration: BoxDecoration(
                        image: widget.voiceNoteList.length < 1 ? null : getDecodedImage(state),
                        borderRadius: BorderRadius.all(
                          Radius.circular(30.0),
                        ),
                      ),
                      child: widget.voiceNoteList.length < 1
                          ? ClipRRect(
                              borderRadius: BorderRadius.all(
                                Radius.circular(30.0),
                              ),
                              child: SvgPicture.asset(
                                "assets/icons/chat_user.svg",
                                clipBehavior: Clip.antiAlias,
                              ),
                            )
                          : null,
                    );
                  },
                ),
              Expanded(
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      widget.surahName,
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                      style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: ColorConsts.primaryBlack, height: 1),
                    ),
                    SizedBox(height: 4),
                    if ((widget.voiceNoteList?.length ?? 0) > 0)
                      StreamBuilder<int>(
                        stream: _player.currentIndexStream,
                        builder: (context, snapshot) {
                          final state = snapshot.data;
                          return Text(
                            (state == null || widget.voiceNoteList.isEmpty) ? "" : widget.voiceNoteList?.elementAt(state)?.userName ?? "",
                            style: TextStyle(fontSize: 10, color: ColorConsts.textGrey1, height: 1),
                          );
                        },
                      ),
                  ],
                ),
              ),
              commonIconButton("assets/icons/download_aya.svg", () async {
                if (await _requestPermission()) {
                  if (await _saveAya()) {
                    Utils.showToast("تم حفظ الآية بنجاح");
                  } else {
                    Utils.showToast("خطأ في حفظ الآية");
                  }
                } else {
                  Utils.showToast("يجب اعطاء الاذن لتنزيل الآية");
                }
              }),
              PopupMenuButton(
                child: commonIconButton("assets/icons/share_aya.svg", null),
                padding: EdgeInsets.fromLTRB(4, 4, 0, 4),
                itemBuilder: (_) => <PopupMenuItem<int>>[
                  PopupMenuItem(
                    value: 1,
                    child: Text(
                      "مشاركة رابط",
                      style: TextStyle(color: ColorConsts.primaryBlack),
                    ),
                  ),
                  PopupMenuItem(
                    value: 2,
                    child: Text(
                      "مشاركة صورة",
                      style: TextStyle(color: ColorConsts.primaryBlack),
                    ),
                  )
                ],
                onSelected: (int value) {
                  if (value == 1) {
                    _shareAyaAsLink();
                  } else {
                    _shareAyaAsImage();
                  }
                },
              )
            ],
          ),
          SizedBox(height: 8),
          if ((widget.voiceNoteList?.length ?? 0) > 0)
            Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                commonIconButton("assets/icons/next_aya.svg", () {
                  _player.seekToNext();
                }),
                SizedBox(width: 4),
                StreamBuilder<PlayerState>(
                  stream: _player.playerStateStream,
                  builder: (context, snapshot) {
                    final state = snapshot.data?.playing ?? false;
                    if (state) {
                      if (_player?.duration?.inSeconds == _player?.position?.inSeconds) {
                        _player.pause();
                        _player.seek(Duration.zero);
                      }
                    }
                    return commonIconButton(state ? "assets/icons/pause.svg" : "assets/icons/play_aya.svg", () {
                      state
                          ? _player.pause()
                          : _isAudioHaveError
                              ? Utils.showToast("خطأ في تحميل ملف الصوت")
                              : _player.play();
                    });
                  },
                ),
                SizedBox(width: 4),
                commonIconButton("assets/icons/previous_aya.svg", () {
                  _player.seekToPrevious();
                }),
                SizedBox(width: 16),
                Expanded(
                  child: StreamBuilder<Duration>(
                    stream: _player.positionStream,
                    builder: (context, snapshot) {
                      final state = snapshot.data;
                      return SliderTheme(
                        data: SliderTheme.of(context).copyWith(
                          inactiveTrackColor: ColorConsts.sliderBackground,
                          activeTrackColor: ColorConsts.secondaryOrange,
                          trackHeight: 8.0,
                          thumbColor: ColorConsts.primaryBlack,
                          thumbShape: RoundSliderThumbShape(enabledThumbRadius: 10.0),
                          overlayColor: ColorConsts.primaryBlack.withAlpha(32),
                          overlayShape: RoundSliderOverlayShape(overlayRadius: 12.0),
                        ),
                        child: Directionality(
                          textDirection: TextDirection.ltr,
                          child: Slider(
                            value: (state?.inSeconds ?? 0) + 0.0,
                            min: 0,
                            max: (_player?.duration?.inSeconds ?? 0) + 0.0,
                            onChanged: (value) {
                              _player.seek(Duration(seconds: value.round()));
                            },
                          ),
                        ),
                      );
                    },
                  ),
                ),
                SizedBox(width: 8),
                StreamBuilder<Duration>(
                  stream: _player.positionStream,
                  builder: (context, snapshot) {
                    final state = snapshot.data;
                    return Text(
                      _durationTime(state) ?? "",
                      style: TextStyle(color: ColorConsts.textGrey1, height: 1.1, fontFamily: "Roboto"),
                    );
                  },
                ),
              ],
            )
        ],
      ),
    );
  }

  String _durationTime(Duration duration) {
    if (duration == null) {
      return "00:00";
    }
    String twoDigits(int n) => n.toString().padLeft(2, "0");
    String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
    String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
    return "$twoDigitMinutes:$twoDigitSeconds";
  }

  Widget commonIconButton(String icon, VoidCallback onPressed) {
    return IconButton(
        highlightColor: Colors.transparent,
        splashColor: Colors.transparent,
        constraints: BoxConstraints(),
        padding: EdgeInsets.only(right: 2),
        icon: SvgPicture.asset(icon, height: 16, width: 16),
        onPressed: onPressed);
  }

  Future<bool> _requestPermission() async {
    Map<Permission, PermissionStatus> statuses = await [
      Permission.storage,
    ].request();

    return statuses[Permission.storage].isGranted;
  }

  Future<bool> _saveAya() async {
    Utils.showLoading(context);
    try {
      RenderRepaintBoundary boundary = widget.globalKey.currentContext.findRenderObject();
      ui.Image image = await boundary.toImage(pixelRatio: 3.0);
      ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
      final result = await ImageGallerySaver.saveImage(byteData.buffer.asUint8List(), quality: 100);
      Utils.hideLoading(context);
      return result["isSuccess"];
    } catch (ex) {
      Future.delayed(Duration(seconds: 1), () {
        Utils.hideLoading(context);
      });
      return false;
    }
  }

  void _shareAyaAsLink() async {
    String _url = "${ApiConsts.baseUrl}/quran/tangheemtype?surahNo=${widget.surahNo}&ayahNo=${widget.ayaNo}&tanghemType=${widget.ayaTangheemTypeId}";
    await Share.share(_url);
  }

  void _shareAyaAsImage() async {
    Utils.showLoading(context);
    try {
      RenderRepaintBoundary boundary = widget.globalKey.currentContext.findRenderObject();
      ui.Image image = await boundary.toImage(pixelRatio: 3.0);
      ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
      Uint8List pngBytes = byteData.buffer.asUint8List();

      final tempDir = await getTemporaryDirectory();
      final file = await File('${tempDir.path}/${DateTime.now().toString()}.png').create();
      await file.writeAsBytes(pngBytes);
      await TangheemUserApiClient().addStatistics(3);
      await Share.shareFiles(['${file.path}']);
      Utils.hideLoading(context);
    } catch (ex) {
      Future.delayed(Duration(seconds: 1), () {
        Utils.hideLoading(context);
      });
    }
  }
}
