import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:ui';

import 'package:device_calendar/device_calendar.dart';
import 'package:manage_calendar_events/manage_calendar_events.dart' as ios;
import 'package:timezone/data/latest.dart' as tzl;

final DeviceCalendarPlugin deviceCalendarPlugin = DeviceCalendarPlugin();
final ios.CalendarPlugin _myPlugin = ios.CalendarPlugin();

class CalendarUtils {
  static Completer<CalendarUtils>? _completer;

  dynamic get writableCalendars => calendars.firstWhere((c) => !c.isReadOnly!);
  dynamic calendars;

  CalendarUtils._(this.calendars);

  // static Future<CalendarUtils> getInstance() async {
  //   if (_completer == null) {
  //     _completer = Completer<CalendarUtils>();
  //     print(_completer!.isCompleted);
  //     try {
  //       final dynamic calendarsResult;
  //       if (Platform.isIOS) {
  //         calendarsResult = await _myPlugin.getCalendars();
  //         if (!_completer!.isCompleted) {
  //           _completer?.complete(CalendarUtils._(await calendarsResult!));
  //         }
  //       } else {
  //         calendarsResult = await deviceCalendarPlugin.retrieveCalendars();
  //         if (!_completer!.isCompleted) {
  //           _completer?.complete(CalendarUtils._(await calendarsResult.data!));
  //         }
  //       }
  //     } on Exception catch (e) {
  //       if (!_completer!.isCompleted) {
  //         _completer!.completeError(e);
  //       }
  //     }
  //   }
  //   return _completer!.future;
  // }

  static Future<CalendarUtils> getInstance() async {
    tzl.initializeTimeZones();
    if (_completer != null) {
      return _completer!.future;
    }
    _completer = Completer<CalendarUtils>();
    try {
      final dynamic calendarsResult;
      if (Platform.isIOS) {
        calendarsResult = await _myPlugin.getCalendars();
        _completer!.complete(CalendarUtils._(calendarsResult));
      } else {
        calendarsResult = await deviceCalendarPlugin.retrieveCalendars();
        _completer!.complete(CalendarUtils._(calendarsResult.data));
      }
    } catch (e) {
      _completer!.completeError(e);
    }

    return _completer!.future;
  }

  Future createOrUpdateEvents({List<DateTime>? scheduleList, String? title, String? description, List<DateTime>? scheduleDateTime, List<DayOfWeek>? daysOfWeek}) async {
    tzl.initializeTimeZones();
    List<Event> events = [];
    Location _currentLocation;
    if (DateTime.now().timeZoneName == "+04")
      _currentLocation = getLocation('Asia/Dubai');
    else
      _currentLocation = getLocation('Asia/Riyadh');

    scheduleDateTime!.forEach((element) {
      RecurrenceRule recurrenceRule = RecurrenceRule(
        // RecurrenceFrequency.Daily,
        // daysOfWeek: daysOfWeek,
        // endDate: element,
        until: element, frequency: Frequency.daily,
      );
      //added byAamir Tz Time
      Event event = Event(writableCalendars!.id,
          recurrenceRule: recurrenceRule,
          start: TZDateTime.from(element, _currentLocation),
          end: TZDateTime.from(element.add(Duration(minutes: 30)), _currentLocation),
          title: title,
          description: description);
      events.add(event);
    });

    events.forEach((element) {
      deviceCalendarPlugin.createOrUpdateEvent(element);
    });
  }

  Future createOrUpdateEvent({required String title, required String description, DateTime? scheduleDateTime, String? eventId}) async {
    RecurrenceRule recurrenceRule = RecurrenceRule(
      // RecurrenceFrequency.Daily,
      // daysOfWeek: daysOfWeek,
      // endDate: scheduleDateTime,
      until: scheduleDateTime, frequency: Frequency.daily,
    );

    Location _currentLocation;
    if (DateTime.now().timeZoneName == "+04")
      _currentLocation = getLocation('Asia/Dubai');
    else
      _currentLocation = getLocation('Asia/Riyadh');

    TZDateTime scheduleDateTimeUTZ = TZDateTime.from(scheduleDateTime!, _currentLocation);

    print("writableCalendars-name:  " + writableCalendars.name);
    print("writableCalendars-Id:  " + writableCalendars.id);
    print("writableCalendarsToString:  " + writableCalendars.toString());
    print("writableCalendarsToString:  " + writableCalendars!.id!);
    Event event = Event(
      writableCalendars!.id,
      start: scheduleDateTimeUTZ,
      end: scheduleDateTimeUTZ.add(Duration(minutes: 30)),
      title: title,
      description: description,
    );

    ios.CalendarEvent iosCalEvent =
        ios.CalendarEvent(eventId: eventId, startDate: scheduleDateTimeUTZ, endDate: scheduleDateTimeUTZ.add(Duration(minutes: 30)), title: title, description: description, isAllDay: false);

    if (Platform.isAndroid) {
      Result<bool> result = await deviceCalendarPlugin.hasPermissions();
      print(result);
      await deviceCalendarPlugin.createOrUpdateEvent(event).catchError((e) {
        print("catchError " + e.toString());
      }).whenComplete(() {
        print("whenComplete Calender ID " + eventId!);
      });
    } else {
      // Result<bool> result = await deviceCalendarPlugin.hasPermissions();
      // print(result);
      await _myPlugin.createEvent(calendarId: writableCalendars.id!, event: iosCalEvent).catchError((e) {
        print("catchError " + e.toString());
      }).whenComplete(() {
        print("whenComplete Calender ID iOS " + eventId!);
      });
    }
  }

  deleteEvent(Calendar _calendar, Event _event) async {
    if (Platform.isIOS) {
      await _myPlugin.deleteEvent(calendarId: _calendar.id!, eventId: _event.eventId!);
    } else {
      await deviceCalendarPlugin.deleteEvent(_calendar.id, _event.eventId);
    }
  }

  Future retrieveEvents(
    String calendarId,
    RetrieveEventsParams retrieveEventsParams,
  ) async {
    return await deviceCalendarPlugin.retrieveEvents(calendarId, retrieveEventsParams);
  }

  Future createCalendar(
    String calendarName, {
    Color? calendarColor,
    String? localAccountName,
  }) async {
    return await deviceCalendarPlugin.createCalendar(calendarName, calendarColor: calendarColor, localAccountName: localAccountName);
  }
}
