package com.google.sps.servlets;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.appengine.datastore.AppEngineDataStoreFactory;

import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.DateTime;
import com.google.api.services.calendar.Calendar;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.calendar.model.EventDateTime;
import com.google.api.services.calendar.model.Event.ExtendedProperties;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.sps.data.Event;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

public class Utils {
  private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
  private static final List<String> SCOPES = Collections.singletonList(CalendarScopes.CALENDAR_EVENTS);

  static String getRedirectUri(HttpServletRequest req) {
    GenericUrl url = new GenericUrl(req.getRequestURL().toString());
    url.setRawPath("/oauth2callback");
    url.set("origin", req.getParameter("origin"));
    return url.build();
  }

  static GoogleAuthorizationCodeFlow newFlow() throws IOException, GeneralSecurityException {
    InputStream in = Utils.class.getResourceAsStream("/credentials.json");
    if (in == null) {
      throw new FileNotFoundException("Resource not found: " + "/credentials.json");
    }
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));

    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
        GoogleNetHttpTransport.newTrustedTransport(), JSON_FACTORY, clientSecrets, SCOPES)
            .setDataStoreFactory(AppEngineDataStoreFactory.getDefaultInstance()).setAccessType("offline")
            .setApprovalPrompt("force").build();
    return flow;
  }

  static Calendar loadCalendarClient() throws IOException, GeneralSecurityException {
    String userId = UserServiceFactory.getUserService().getCurrentUser().getUserId();
    Credential credential = newFlow().loadCredential(userId);
    if (credential == null)
      return null;
    return new Calendar.Builder(GoogleNetHttpTransport.newTrustedTransport(), JacksonFactory.getDefaultInstance(),
        credential).setApplicationName("SEE").build();
  }

  static com.google.api.services.calendar.model.Event createGCalendarEvent(com.google.sps.data.Event event)
      throws IOException {
    com.google.api.services.calendar.model.Event gcalendarEvent = new com.google.api.services.calendar.model.Event();
    gcalendarEvent.setDescription(event.getDescription()).setSummary(event.getTitle());
    DateTime startDateTime = new DateTime(event.getDateTimeAsString());
    DateTime endDateTime = new DateTime(startDateTime.getValue() + event.getDuration() * 60 * 1000);
    gcalendarEvent.setStart(new EventDateTime().setDateTime(startDateTime));
    gcalendarEvent.setEnd(new EventDateTime().setDateTime(endDateTime));

    ExtendedProperties extendedProps = new ExtendedProperties();
    extendedProps.setShared(event.getFields());
    gcalendarEvent.setExtendedProperties(extendedProps);

    try {
      Calendar service = loadCalendarClient();
      if (service == null){
        return null;
      }
      service.events().insert("primary", gcalendarEvent).execute();
      return gcalendarEvent;
    } catch (GeneralSecurityException e) {
      e.printStackTrace();
    }
    return null;
  }

}

@@ -692,24 +692,85 @@
 ndarScopes;%0A
+import com.google.api.services.calendar.model.EventAttendee;%0A
 import com.g
@@ -1150,32 +1150,60 @@
 urityException;%0A
+import java.util.ArrayList;%0A
 import java.util
@@ -3774,17 +3774,16 @@
 Props);%0A
-%0A
     try 
@@ -3857,16 +3857,17 @@
 == null)
+ 
 %7B%0A      
@@ -3894,16 +3894,33 @@
  %7D%0A     
+ gcalendarEvent =
  service
@@ -3963,16 +3963,38 @@
 rEvent).
+setSendUpdates(%22all%22).
 execute(
@@ -4099,20 +4099,16 @@
 ();%0A    
-%7D%0A  
   return
@@ -4108,21 +4108,1035 @@
  return null
+;%0A    %7D%0A  %7D%0A%0A  static void joinGCalendarEvent(String ownerId, String eventId, String userToBeAddedEmail)%0A      throws GeneralSecurityException, IOException %7B%0A    Credential credential = newFlow().loadCredential(ownerId);%0A    Calendar ownerCalendar = new Calendar.Builder(GoogleNetHttpTransport.newTrustedTransport(),%0A        JacksonFactory.getDefaultInstance(), credential).setApplicationName(%22SEE%22).build();%0A    com.google.api.services.calendar.model.Event originalEvent = ownerCalendar.events().get(%22primary%22, eventId)%0A        .execute();%0A    List%3CEventAttendee%3E currentAttendees = originalEvent.getAttendees();%0A    EventAttendee newAttendee = new EventAttendee().setEmail(userToBeAddedEmail)%0A        .setResponseStatus(%22accepted%22);%0A    if (currentAttendees == null)%0A      currentAttendees = new ArrayList%3C%3E();%0A    currentAttendees.add(newAttendee);%0A    originalEvent.setAttendees(currentAttendees);%0A    ownerCalendar.events().patch(%22primary%22, eventId, originalEvent).setSendUpdates(%22all%22).execute();%0A    return 
 ;%0A  %7D%0A%0A%7D%0A

Add method for adding a participant by email to a given GCalendarEvent (#20)