/*
 * 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.android.gnd.persistence.local.room;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.room.Embedded;
import com.google.android.gnd.model.AuditInfo;
import com.google.auto.value.AutoValue;
import com.google.auto.value.AutoValue.CopyAnnotations;
import java.util.Date;
import java8.util.Optional;

/** User details and timestamp for creation or modification of a model object. */
@AutoValue
public abstract class AuditInfoEntity {

  /**
   * Returns the user initiating the related action. This can never be null, since users must always
   * be logged in to make changes.
   */
  @CopyAnnotations
  @Embedded(prefix = "user_")
  @NonNull
  public abstract UserDetails getUser();

  /** Returns the time at which the user action was initiated, according to the user's device. */
  @CopyAnnotations
  public abstract long getClientTimeMillis();

  /**
   * Returns the time at which the server received the requested change according to the server's
   * internal clock, or null if the updated server time was not yet received.
   */
  @CopyAnnotations
  @Nullable
  public abstract Long getServerTimeMillis();

  /** Converts a model object into a local db entity. */
  public static AuditInfoEntity fromObject(AuditInfo o) {
    return AuditInfoEntity.builder()
        .setUser(UserDetails.fromUser(o.getUser()))
        .setClientTimeMillis(o.getClientTimeMillis().getTime())
        .setServerTimeMillis(o.getServerTimeMillis().map(Date::getTime).orElse(null))
        .build();
  }

  public static AuditInfo toObject(AuditInfoEntity e) {
    return AuditInfo.builder()
        .setUser(UserDetails.toUser(e.getUser()))
        .setClientTimeMillis(new Date(e.getClientTimeMillis()))
        .setServerTimeMillis(Optional.ofNullable(e.getServerTimeMillis()).map(Date::new))
        .build();
  }

  // Generated by AutoValue plugin:

  @NonNull
  public static AuditInfoEntity create(
      @NonNull UserDetails user, long clientTimeMillis, @Nullable Long serverTimeMillis) {
    return builder()
        .setUser(user)
        .setClientTimeMillis(clientTimeMillis)
        .setServerTimeMillis(serverTimeMillis)
        .build();
  }

  public static Builder builder() {
    return new AutoValue_AuditInfoEntity.Builder();
  }

  @AutoValue.Builder
  public abstract static class Builder {

    public abstract Builder setUser(UserDetails newUser);

    public abstract Builder setClientTimeMillis(@NonNull long newClientTimeMillis);

    public abstract Builder setServerTimeMillis(@Nullable Long newServerTimeMillis);

    public abstract AuditInfoEntity build();
  }
}

/*
 * 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.android.gnd.persistence.local.room;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.room.Embedded;
import com.google.android.gnd.model.AuditInfo;
import com.google.auto.value.AutoValue;
import com.google.auto.value.AutoValue.CopyAnnotations;
import java.util.Date;
import java8.util.Optional;

/** User details and timestamp for creation or modification of a model object. */
@AutoValue
public abstract class AuditInfoEntity {

  /**
   * Returns the user initiating the related action. This can never be null, since users must always
   * be logged in to make changes.
   */
  @CopyAnnotations
  @Embedded(prefix = "user_")
  @NonNull
  public abstract UserDetails getUser();

  /** Returns the time at which the user action was initiated, according to the user's device. */
  @CopyAnnotations
  @NonNull
  public abstract Long getClientTimeMillis();

  /**
   * Returns the time at which the server received the requested change according to the server's
   * internal clock, or null if the updated server time was not yet received.
   */
  @CopyAnnotations
  @Nullable
  public abstract Long getServerTimeMillis();

  /** Converts a model object into a local db entity. */
  public static AuditInfoEntity fromObject(AuditInfo o) {
    return AuditInfoEntity.builder()
        .setUser(UserDetails.fromUser(o.getUser()))
        .setClientTimeMillis(o.getClientTimeMillis().getTime())
        .setServerTimeMillis(o.getServerTimeMillis().map(Date::getTime).orElse(null))
        .build();
  }

  public static AuditInfo toObject(AuditInfoEntity e) {
    return AuditInfo.builder()
        .setUser(UserDetails.toUser(e.getUser()))
        .setClientTimeMillis(new Date(e.getClientTimeMillis()))
        .setServerTimeMillis(Optional.ofNullable(e.getServerTimeMillis()).map(Date::new))
        .build();
  }

  // Generated by AutoValue plugin:

  @NonNull
  public static AuditInfoEntity create(
      @NonNull UserDetails user, long clientTimeMillis, @Nullable Long serverTimeMillis) {
    return builder()
        .setUser(user)
        .setClientTimeMillis(clientTimeMillis)
        .setServerTimeMillis(serverTimeMillis)
        .build();
  }

  public static Builder builder() {
    return new AutoValue_AuditInfoEntity.Builder();
  }

  @AutoValue.Builder
  public abstract static class Builder {

    public abstract Builder setUser(UserDetails newUser);

    public abstract Builder setClientTimeMillis(@NonNull Long newClientTimeMillis);

    public abstract Builder setServerTimeMillis(@Nullable Long newServerTimeMillis);

    public abstract AuditInfoEntity build();
  }
}

Use Long for consistency