import '../../../../../api/demo/data/demo_timetable.dart';
import '../../../../../api/demo/demo_mode.dart';
import '../../../../../api/marianumconnect/queries/timetable_custom_events/timetable_custom_events_add.dart';
import '../../../../../api/marianumconnect/queries/timetable_custom_events/timetable_custom_events_cache.dart';
import '../../../../../api/marianumconnect/queries/timetable_custom_events/timetable_custom_events_remove.dart';
import '../../../../../api/marianumconnect/queries/timetable_custom_events/timetable_custom_events_update.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_holidays/timetable_get_holidays.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_holidays/timetable_get_holidays_response.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_rooms/timetable_get_rooms.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_rooms/timetable_get_rooms_response.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_schoolyear/timetable_get_schoolyear.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_schoolyear/timetable_get_schoolyear_response.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_subjects/timetable_get_subjects.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_subjects/timetable_get_subjects_response.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_timegrid/timetable_get_timegrid.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_timegrid/timetable_get_timegrid_response.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_week/timetable_get_week.dart';
import '../../../../../api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart';
import '../../../../../api/marianumconnect/queries/timetable_subject_colors/timetable_subject_color_remove.dart';
import '../../../../../api/marianumconnect/queries/timetable_subject_colors/timetable_subject_color_set.dart';
import '../../../../../api/mhsl/custom_timetable_event/custom_timetable_event.dart';
import '../../../../../api/mhsl/custom_timetable_event/get/get_custom_timetable_event_response.dart';
import '../../../../../api/request_cache.dart';

/// Pulls the timetable from the Marianum-Connect mobile API. Each endpoint is
/// its own HTTP call; this provider exposes the lazy futures so the bloc can
/// chain them without seeing the dio layer.
class TimetableDataProvider {
  Future<TimetableGetWeekResponse> getWeek(
    DateTime startDate,
    DateTime endDate, {
    void Function(Object)? onError,
    bool renew = false,
  }) async {
    try {
      return await TimetableGetWeek().run(from: startDate, until: endDate);
    } catch (e) {
      onError?.call(e);
      rethrow;
    }
  }

  Future<TimetableGetRoomsResponse> getRooms({
    void Function(Object)? onError,
    bool renew = false,
  }) async {
    try {
      return await TimetableGetRooms().run();
    } catch (e) {
      onError?.call(e);
      rethrow;
    }
  }

  Future<TimetableGetSubjectsResponse> getSubjects({
    void Function(Object)? onError,
    bool renew = false,
  }) async {
    try {
      return await TimetableGetSubjects().run();
    } catch (e) {
      onError?.call(e);
      rethrow;
    }
  }

  Future<TimetableGetHolidaysResponse> getSchoolHolidays({
    void Function(Object)? onError,
    bool renew = false,
  }) async {
    try {
      return await TimetableGetHolidays().run();
    } catch (e) {
      onError?.call(e);
      rethrow;
    }
  }

  Future<TimetableGetSchoolyearResponse> getCurrentSchoolyear({
    void Function(Object)? onError,
    bool renew = false,
  }) async {
    try {
      return await TimetableGetSchoolyear().run();
    } catch (e) {
      onError?.call(e);
      rethrow;
    }
  }

  Future<TimetableGetTimegridResponse> getTimegrid({bool renew = false}) =>
      TimetableGetTimegrid().run();

  Future<GetCustomTimetableEventResponse> getCustomEvents({
    bool renew = false,
    void Function(Object)? onError,
  }) {
    if (DemoMode.active) return Future.value(DemoTimetable.customEvents());
    return resolveFromCache<GetCustomTimetableEventResponse>(
      (onUpdate, onError) => TimetableCustomEventsCache(
        renew: renew,
        onUpdate: onUpdate,
        onError: onError,
      ),
      onError: onError,
      operationName: 'getCustomEvents',
    );
  }

  Future<void> addCustomEvent(CustomTimetableEvent event) {
    if (DemoMode.active) return Future.value();
    return TimetableCustomEventsAdd().run(event);
  }

  Future<void> updateCustomEvent(String id, CustomTimetableEvent event) {
    if (DemoMode.active) return Future.value();
    return TimetableCustomEventsUpdate().run(id, event);
  }

  Future<void> removeCustomEvent(String id) {
    if (DemoMode.active) return Future.value();
    return TimetableCustomEventsRemove().run(id);
  }

  Future<void> setSubjectColor(String subjectShort, String color) {
    if (DemoMode.active) return Future.value();
    return TimetableSubjectColorSet().run(subjectShort, color);
  }

  Future<void> removeSubjectColor(String subjectShort) {
    if (DemoMode.active) return Future.value();
    return TimetableSubjectColorRemove().run(subjectShort);
  }
}
