/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.vinet.data;

import com.google.appengine.api.datastore.*;
import java.time.Instant;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.*;

public class IsolateTimeSlot extends TimeSlot implements Datastoreable{
  protected final static String ISOLATE_TIME_SLOT_TABLE_NAME = "IsolateTimeSlot";

  protected final Key ticket;
  protected final LocalDate date;
  protected final DatastoreService datastore;

  public IsolateTimeSlot(Entity entity){
    super(
        Instant.parse((String)entity.getProperty("startTime")),
        Instant.parse((String)entity.getProperty("endTime")),
        new Isolate((String) entity.getProperty("isolateId"))
    );
    this.ticket = KeyFactory.stringToKey((String) entity.getProperty("ticketKey"));
    this.date = LocalDate.parse((String) entity.getProperty("date"));
    this.datastore = DatastoreServiceFactory.getDatastoreService();
  }

  /**
   * Construct an IsolateTimeSlot with a dependency on the default implementation of Datastore.
   * @param start The start of the TimeSlot.
   * @param end The end of the TimeSlot.
   * @param isolate The isolate associated with the TimeSlot.
   * @param date The date on which the TimeSlot is scheduled.
   * @param ticket The Datastore key of the request ticket for this TimeSlot.
   */
  public IsolateTimeSlot(Instant start, Instant end, Isolate isolate, LocalDate date, Key ticket) {
    this(start, end, isolate, date, ticket, DatastoreServiceFactory.getDatastoreService());
  }

  /**
   Construct an IsolateTimeSlot with a dependency on the provided implementation of Datastore.
   * @param start The start of the TimeSlot.
   * @param end The end of the TimeSlot.
   * @param isolate The isolate associated with the TimeSlot.
   * @param date The date on which the TimeSlot is scheduled.
   * @param ticket The Datastore key of the request ticket for this TimeSlot.
   * @param datastore The implementation of Datastore to depend on.
   */
  public IsolateTimeSlot(Instant start, Instant end, Isolate isolate, LocalDate date, Key ticket, DatastoreService datastore) {
    super(start, end, isolate);
    this.date = date;
    this.ticket = ticket;
    this.datastore = datastore;
  }

  public Isolate getIsolate() {
    return (Isolate) registeredUser;
  }

  public static List<IsolateTimeSlot> getTimeslotsByUserId(String userId) {
    return StreamSupport.stream(queryTimeSlots(userId).asIterable().spliterator(), true)
        .map(IsolateTimeSlot::new)
        .collect(Collectors.toList());
  }

  private static PreparedQuery queryTimeSlots(String userId) {
    Query query =
        new Query(ISOLATE_TIME_SLOT_TABLE_NAME)
            .setFilter(new Query.FilterPredicate("userId", Query.FilterOperator.EQUAL, userId));

    final DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();

    return datastoreService.prepare(query);
  }

  /**
   * Put this IsolateTimeSlot into Datstore.
   */
  @Override
  public void toDatastore() {
    /* TODO: Check that all instance variables are non-null before posting to Datastore. */
    final  Entity entity = new Entity(ISOLATE_TIME_SLOT_TABLE_NAME);
    entity.setProperty("ticketKey", KeyFactory.keyToString(ticket));
    entity.setProperty("isolateId", this.getIsolate().userId);
    entity.setProperty("date", date.toString());
    entity.setProperty("startTime", start.toString());
    entity.setProperty("endTime", end.toString());

    this.datastore.put(entity);
  }
}

@@ -662,24 +662,170 @@
 atastore.*;%0A
+import com.google.appengine.api.datastore.Entity;%0Aimport com.google.appengine.api.datastore.Key;%0Aimport com.google.appengine.api.datastore.Query;%0A
 import java.
@@ -1136,30 +1136,28 @@
 ate;%0A  p
-rotected final
+ublic static
  Datasto
@@ -1223,21 +1223,20 @@
 y)%7B%0A    
-super
+this
 (%0A      
@@ -1420,115 +1420,17 @@
 d%22))
+,
 %0A    
-);%0A
    
- this.ticket = KeyFactory.stringToKey((String) entity.getProperty(%22ticketKey%22));%0A    this.date =
  Loc
@@ -1482,775 +1482,132 @@
 e%22))
-;
+,
 %0A    
-this.datastore = DatastoreServiceFactory.getDatastoreService();%0A  %7D%0A%0A  /**%0A   * Construct an IsolateTimeSlot with a dependency on the default implementation of Datastore.%0A   * @param start The start of the TimeSlot.%0A   * @param end The end of the TimeSlot.%0A   * @param isolate The isolate associated with the TimeSlot.%0A   * @param date The date on which the TimeSlot is scheduled.%0A   * @param ticket The Datastore key of the request ticket for this TimeSlot.%0A   */%0A  public IsolateTimeSlot(Instant start, Instant end, Isolate isolate, LocalDate date, Key ticket) %7B%0A    this(start, end, isolate, date, ticket, DatastoreServiceFactory.getDatastoreService());%0A  %7D%0A%0A  /**%0A   Construct an IsolateTimeSlot with a dependency on the provided implementation of Datastore
+    KeyFactory.stringToKey((String) entity.getProperty(%22ticketKey%22))%0A    );%0A  %7D%0A%0A  /**%0A   Construct an IsolateTimeSlot
 .%0A  
@@ -1896,76 +1896,8 @@
 ot.%0A
-   * @param datastore The implementation of Datastore to depend on.%0A
    *
@@ -1998,36 +1998,8 @@
 cket
-, DatastoreService datastore
 ) %7B%0A
@@ -2082,40 +2082,8 @@
 et;%0A
-    this.datastore = datastore;%0A
   %7D%0A
@@ -2632,102 +2632,8 @@
 );%0A%0A
-    final DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();%0A%0A
     
@@ -2648,23 +2648,16 @@
 atastore
-Service
 .prepare
@@ -3222,21 +3222,16 @@
 );%0A%0A    
-this.
 datastor

refactor constructor for entity