import 'dart:convert';

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

import '../errors/network_exception.dart';
import '../errors/parse_exception.dart';
import '../errors/server_exception.dart';
import '../http_errors.dart';

abstract class MhslApi<T> {
  String subpath;
  MhslApi(this.subpath);

  Future<http.Response>? request(Uri uri);
  T assemble(String raw);

  Future<T> run() async {
    final endpoint = Uri.parse(
      'https://mhsl.eu/marianum/marianummobile/$subpath',
    );

    final data = await sendGuarded('mhsl $subpath', () => request(endpoint));
    if (data == null) {
      throw const NetworkException(
        userMessage: 'Keine Antwort vom MHSL-Dienst erhalten.',
        technicalDetails: 'mhsl request returned null',
      );
    }

    if (data.statusCode > 299) {
      throw ServerException(
        statusCode: data.statusCode,
        technicalDetails: 'mhsl $subpath HTTP ${data.statusCode}',
      );
    }

    try {
      return assemble(utf8.decode(data.bodyBytes));
    } catch (e) {
      throw ParseException(technicalDetails: 'mhsl $subpath assemble: $e');
    }
  }
}
