import 'dart:convert';
import 'package:http/http.dart' as http;

import 'package:nut_player/nut_player.dart';
import 'package:nut_player/src/provider/json_provider/model/json_content.dart';
import 'package:nut_player/src/provider/json_provider/model/json_error.dart';
import 'package:nut_player/src/provider/json_provider/model/json_statistics.dart';
import 'package:nut_player/src/provider/json_provider/model/json_subtitles.dart';
import 'package:nut_player/src/provider/json_provider/parsing/response.dart';

class JsonProvider extends Provider {
  final String urlPath;

  JsonProvider(this.urlPath);

  @override
  Future<PlayerContent> retrieveContent() async {
    final response = await http.get(Uri.parse(urlPath));

    if (response.statusCode == 200) {
      return _handleSucceedResponse(response);
    } else {
      throw JsonBadStatusCodeError();
    }
  }

  JsonContent _handleSucceedResponse(http.Response httpResponse) {
    var response = Response.fromJson(jsonDecode(httpResponse.body) as Map<String, dynamic>);

    if (response.playbacks.isEmpty) { throw JsonNoPlaybacksError(); }
    var uri = Uri.tryParse(response.playbacks.first.streamUrl);
    if (uri != null) {
      final statistics = response.statistics.map((stat) =>
          JsonStatistics(
              stat.name,
              stat.urlTemplate,
              stat.start,
              stat.delay,
              stat.count,
              stat.method == "get" ? HTTPMethod.get : HTTPMethod.post,
              stat.body
          )
      );

      final subtitles = response.subtitles.map((sub) =>
          JsonSubtitles(
              sub.title,
              sub.type == "srt" ? SubtitleType.srt : SubtitleType.unknown,
              sub.url,
              sub.language
          )
      );

      final ContentType? contentType;
      final urlPath = uri.toString();
      if (urlPath.endsWith('.mp4')) {
        contentType = Mp4ContentType(urlPath: urlPath);
      } else if (urlPath.endsWith('.m3u8')) {
        final isLive = response.playbacks.first.isLive;
        contentType = HlsContentType(urlPath: urlPath, isLive: isLive);
      } else {
        contentType = null;
      }

      if (contentType != null) {
        return JsonContent(
            contentType,
            statistics.toList(),
            subtitles.toList()
        );
      } else {
        throw JsonUnknownFormatError();
      }
    } else {
      throw JsonIncorrectUrlError();
    }
  }
}