// Copyright (C) 2018 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.entities.converter;

import com.google.errorprone.annotations.Immutable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.proto.Entities;
import com.google.protobuf.Parser;
import java.time.Instant;

@Immutable
public enum ChangeProtoConverter implements ProtoConverter<Entities.Change, Change> {
  INSTANCE;

  private final ProtoConverter<Entities.Change_Id, Change.Id> changeIdConverter =
      ChangeIdProtoConverter.INSTANCE;
  private final ProtoConverter<Entities.PatchSet_Id, PatchSet.Id> patchSetIdConverter =
      PatchSetIdProtoConverter.INSTANCE;
  private final ProtoConverter<Entities.Change_Key, Change.Key> changeKeyConverter =
      ChangeKeyProtoConverter.INSTANCE;
  private final ProtoConverter<Entities.Account_Id, Account.Id> accountIdConverter =
      AccountIdProtoConverter.INSTANCE;
  private final ProtoConverter<Entities.Branch_NameKey, BranchNameKey> branchNameConverter =
      BranchNameKeyProtoConverter.INSTANCE;

  @Override
  public Entities.Change toProto(Change change) {
    Entities.Change.Builder builder =
        Entities.Change.newBuilder()
            .setChangeId(changeIdConverter.toProto(change.getId()))
            .setChangeKey(changeKeyConverter.toProto(change.getKey()))
            .setCreatedOn(change.getCreatedOn().toEpochMilli())
            .setLastUpdatedOn(change.getLastUpdatedOn().toEpochMilli())
            .setOwnerAccountId(accountIdConverter.toProto(change.getOwner()))
            .setDest(branchNameConverter.toProto(change.getDest()))
            .setStatus(change.getStatus().getCode())
            .setIsPrivate(change.isPrivate())
            .setWorkInProgress(change.isWorkInProgress())
            .setReviewStarted(change.hasReviewStarted());
    PatchSet.Id currentPatchSetId = change.currentPatchSetId();
    // Special behavior necessary to ensure binary compatibility.
    builder.setCurrentPatchSetId(currentPatchSetId == null ? 0 : currentPatchSetId.get());
    String subject = change.getSubject();
    if (subject != null) {
      builder.setSubject(subject);
    }
    String topic = change.getTopic();
    if (topic != null) {
      builder.setTopic(topic);
    }
    String originalSubject = change.getOriginalSubjectOrNull();
    if (originalSubject != null) {
      builder.setOriginalSubject(originalSubject);
    }
    String submissionId = change.getSubmissionId();
    if (submissionId != null) {
      builder.setSubmissionId(submissionId);
    }
    Change.Id revertOf = change.getRevertOf();
    if (revertOf != null) {
      builder.setRevertOf(changeIdConverter.toProto(revertOf));
    }
    PatchSet.Id cherryPickOf = change.getCherryPickOf();
    if (cherryPickOf != null) {
      builder.setCherryPickOf(patchSetIdConverter.toProto(cherryPickOf));
    }
    String serverId = change.getServerId();
    if (serverId != null) {
      builder.setServerId(serverId);
    }
    return builder.build();
  }

  @Override
  public Change fromProto(Entities.Change proto) {
    Change.Id changeId = changeIdConverter.fromProto(proto.getChangeId());
    Change.Key key =
        proto.hasChangeKey() ? changeKeyConverter.fromProto(proto.getChangeKey()) : null;
    Account.Id owner =
        proto.hasOwnerAccountId() ? accountIdConverter.fromProto(proto.getOwnerAccountId()) : null;
    BranchNameKey destination =
        proto.hasDest() ? branchNameConverter.fromProto(proto.getDest()) : null;
    Change change =
        new Change(key, changeId, owner, destination, Instant.ofEpochMilli(proto.getCreatedOn()));
    if (proto.hasLastUpdatedOn()) {
      change.setLastUpdatedOn(Instant.ofEpochMilli(proto.getLastUpdatedOn()));
    }
    Change.Status status = Change.Status.forCode((char) proto.getStatus());
    if (status != null) {
      change.setStatus(status);
    }
    String subject = proto.hasSubject() ? proto.getSubject() : null;
    String originalSubject = proto.hasOriginalSubject() ? proto.getOriginalSubject() : null;
    change.setCurrentPatchSet(
        PatchSet.id(changeId, proto.getCurrentPatchSetId()), subject, originalSubject);
    if (proto.hasTopic()) {
      change.setTopic(proto.getTopic());
    }
    if (proto.hasSubmissionId()) {
      change.setSubmissionId(proto.getSubmissionId());
    }
    change.setPrivate(proto.getIsPrivate());
    change.setWorkInProgress(proto.getWorkInProgress());
    change.setReviewStarted(proto.getReviewStarted());
    if (proto.hasRevertOf()) {
      change.setRevertOf(changeIdConverter.fromProto(proto.getRevertOf()));
    }
    if (proto.hasCherryPickOf()) {
      change.setCherryPickOf(patchSetIdConverter.fromProto(proto.getCherryPickOf()));
    }
    if (proto.hasServerId()) {
      change.setServerId(proto.getServerId());
    }
    return change;
  }

  @Override
  public Parser<Entities.Change> getParser() {
    return Entities.Change.parser();
  }
}
