// Copyright (C) 2017 The Android Open Source Project
//
// 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
//
// http://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.gerrit.server.notedb;

import static com.google.common.truth.Truth.assertThat;

import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.HumanComment;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.sql.Timestamp;
import java.time.ZonedDateTime;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class CommentTimestampAdapterTest {
  /** Arbitrary time outside of a DST transition, as an ISO instant. */
  private static final String NON_DST_STR = "2017-02-07T10:20:30.123Z";

  /** Arbitrary time outside of a DST transition, as a reasonable Java 11 representation. */
  private static final ZonedDateTime NON_DST = ZonedDateTime.parse(NON_DST_STR);

  /** {@link #NON_DST_STR} truncated to seconds. */
  private static final String NON_DST_STR_TRUNC = "2017-02-07T10:20:30Z";

  /** Arbitrary time outside of a DST transition, as an unreasonable Timestamp representation. */
  private static final Timestamp NON_DST_TS = Timestamp.from(NON_DST.toInstant());

  /** {@link #NON_DST_TS} truncated to seconds. */
  private static final Timestamp NON_DST_TS_TRUNC =
      Timestamp.from(ZonedDateTime.parse(NON_DST_STR_TRUNC).toInstant());

  /**
   * Real live ms since epoch timestamp of a comment that was posted during the PDT to PST
   * transition in November 2013.
   */
  private static final long MID_DST_MS = 1383466224175L;

  /**
   * Ambiguous string representation of {@link #MID_DST_MS} that was actually stored in NoteDb for
   * this comment.
   */
  private static final String MID_DST_STR = "Nov 3, 2013 1:10:24 AM";

  private TimeZone systemTimeZone;
  private Gson legacyGson;
  private Gson gson;

  @Before
  public void setUp() {
    systemTimeZone = TimeZone.getDefault();
    TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));

    // Match ChangeNoteUtil#gson as of 4e1f02db913d91f2988f559048e513e6093a1bce
    legacyGson = new GsonBuilder().setPrettyPrinting().create();
    gson = ChangeNoteJson.newGson();
  }

  @After
  public void tearDown() {
    TimeZone.setDefault(systemTimeZone);
  }

  @Test
  public void legacyGsonBehavesAsExpectedDuringDstTransition() {
    long oneHourMs = TimeUnit.HOURS.toMillis(1);

    String beforeJson = "\"Nov 3, 2013 12:10:24 AM\"";
    Timestamp beforeTs = new Timestamp(MID_DST_MS - oneHourMs);
    assertThat(legacyGson.toJson(beforeTs)).isEqualTo(beforeJson);

    String ambiguousJson = '"' + MID_DST_STR + '"';
    Timestamp duringTs = new Timestamp(MID_DST_MS);
    assertThat(legacyGson.toJson(duringTs)).isEqualTo(ambiguousJson);

    Timestamp afterTs = new Timestamp(MID_DST_MS + oneHourMs);
    assertThat(legacyGson.toJson(afterTs)).isEqualTo(ambiguousJson);

    Timestamp beforeTsTruncated = new Timestamp(beforeTs.getTime() / 1000 * 1000);
    assertThat(legacyGson.fromJson(beforeJson, Timestamp.class)).isEqualTo(beforeTsTruncated);

    // Gson just picks one, and it happens to be the one after the PST transition.
    Timestamp afterTsTruncated = new Timestamp(afterTs.getTime() / 1000 * 1000);
    assertThat(legacyGson.fromJson(ambiguousJson, Timestamp.class)).isEqualTo(afterTsTruncated);
  }

  @Test
  public void legacyAdapterViaZonedDateTime() {
    assertThat(legacyGson.toJson(NON_DST_TS)).isEqualTo("\"Feb 7, 2017 2:20:30 AM\"");
  }

  @Test
  public void legacyAdapterCanParseOutputOfNewAdapter() {
    String instantJson = gson.toJson(NON_DST_TS);
    assertThat(instantJson).isEqualTo('"' + NON_DST_STR_TRUNC + '"');
    Timestamp result = legacyGson.fromJson(instantJson, Timestamp.class);
    assertThat(result).isEqualTo(NON_DST_TS_TRUNC);
  }

  @Test
  public void newAdapterCanParseOutputOfLegacyAdapter() {
    String legacyJson = legacyGson.toJson(NON_DST_TS);
    assertThat(legacyJson).isEqualTo("\"Feb 7, 2017 2:20:30 AM\"");
    assertThat(gson.fromJson(legacyJson, Timestamp.class))
        .isEqualTo(new Timestamp(NON_DST_TS.getTime() / 1000 * 1000));
  }

  @Test
  public void newAdapterDisagreesWithLegacyAdapterDuringDstTransition() {
    String duringJson = legacyGson.toJson(new Timestamp(MID_DST_MS));
    Timestamp duringTs = legacyGson.fromJson(duringJson, Timestamp.class);

    // This is unfortunate, but it's just documenting the current behavior, there is no real good
    // solution here. The goal is that all these changes will be rebuilt with proper UTC instant
    // strings shortly after the new adapter is live.
    Timestamp newDuringTs = gson.fromJson(duringJson, Timestamp.class);
    assertThat(newDuringTs.toString()).isEqualTo(duringTs.toString());
    assertThat(newDuringTs).isNotEqualTo(duringTs);
  }

  @Test
  public void newAdapterRoundTrip() {
    String json = gson.toJson(NON_DST_TS);
    // Round-trip lossily truncates ms, but that's ok.
    assertThat(json).isEqualTo('"' + NON_DST_STR_TRUNC + '"');
    assertThat(gson.fromJson(json, Timestamp.class)).isEqualTo(NON_DST_TS_TRUNC);
  }

  @Test
  public void nullSafety() {
    assertThat(gson.toJson(null, Timestamp.class)).isEqualTo("null");
    assertThat(gson.fromJson("null", Timestamp.class)).isNull();
  }

  @Test
  public void newAdapterRoundTripOfWholeComment() {
    Comment c =
        new HumanComment(
            new Comment.Key("uuid", "filename", 1),
            Account.id(100),
            NON_DST_TS.toInstant(),
            (short) 0,
            "message",
            "serverId",
            false);
    c.lineNbr = 1;
    c.setCommitId(ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));

    String json = gson.toJson(c);
    assertThat(json).contains("\"writtenOn\": \"" + NON_DST_STR_TRUNC + "\",");

    Comment result = gson.fromJson(json, HumanComment.class);
    // Round-trip lossily truncates ms, but that's ok.
    assertThat(result.writtenOn).isEqualTo(NON_DST_TS_TRUNC);
    result.writtenOn = NON_DST_TS;
    assertThat(result).isEqualTo(c);
  }
}
