// Copyright (C) 2014 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.restapi.change;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.common.DiffWebLinkInfo;
import com.google.gerrit.extensions.common.EditInfo;
import com.google.gerrit.extensions.common.Input;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ChildCollection;
import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.RawInput;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestCollectionCreateView;
import com.google.gerrit.extensions.restapi.RestCollectionDeleteMissingView;
import com.google.gerrit.extensions.restapi.RestCollectionModifyView;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.server.WebLinks;
import com.google.gerrit.server.change.ChangeEditResource;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.FileContentUtil;
import com.google.gerrit.server.change.FileInfoJson;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.edit.ChangeEdit;
import com.google.gerrit.server.edit.ChangeEditJson;
import com.google.gerrit.server.edit.ChangeEditModifier;
import com.google.gerrit.server.edit.ChangeEditUtil;
import com.google.gerrit.server.edit.UnchangedCommitMessageException;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.kohsuke.args4j.Option;

@Singleton
public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditResource> {
  private final DynamicMap<RestView<ChangeEditResource>> views;
  private final Provider<Detail> detail;
  private final ChangeEditUtil editUtil;

  @Inject
  ChangeEdits(
      DynamicMap<RestView<ChangeEditResource>> views,
      Provider<Detail> detail,
      ChangeEditUtil editUtil) {
    this.views = views;
    this.detail = detail;
    this.editUtil = editUtil;
  }

  @Override
  public DynamicMap<RestView<ChangeEditResource>> views() {
    return views;
  }

  @Override
  public RestView<ChangeResource> list() {
    return detail.get();
  }

  @Override
  public ChangeEditResource parse(ChangeResource rsrc, IdString id)
      throws ResourceNotFoundException, AuthException, IOException {
    Optional<ChangeEdit> edit = editUtil.byChange(rsrc.getNotes(), rsrc.getUser());
    if (!edit.isPresent()) {
      throw new ResourceNotFoundException(id);
    }
    return new ChangeEditResource(rsrc, edit.get(), id.get());
  }

  /**
   * Create handler that is activated when collection element is accessed but doesn't exist, e. g.
   * PUT request with a path was called but change edit wasn't created yet. Change edit is created
   * and PUT handler is called.
   */
  public static class Create
      implements RestCollectionCreateView<ChangeResource, ChangeEditResource, Put.Input> {
    private final Put putEdit;

    @Inject
    Create(Put putEdit) {
      this.putEdit = putEdit;
    }

    @Override
    public Response<?> apply(ChangeResource resource, IdString id, Put.Input input)
        throws AuthException, ResourceConflictException, BadRequestException, IOException,
            PermissionBackendException, BadRequestException {
      putEdit.apply(resource, id.get(), input.content);
      return Response.none();
    }
  }

  public static class DeleteFile
      implements RestCollectionDeleteMissingView<ChangeResource, ChangeEditResource, Input> {
    private final DeleteContent deleteContent;

    @Inject
    DeleteFile(DeleteContent deleteContent) {
      this.deleteContent = deleteContent;
    }

    @Override
    public Response<?> apply(ChangeResource rsrc, IdString id, Input in)
        throws IOException, AuthException, BadRequestException, ResourceConflictException,
            PermissionBackendException {
      return deleteContent.apply(rsrc, id.get());
    }
  }

  // TODO(davido): Turn the boolean options to ChangeEditOption enum,
  // like it's already the case for ListChangesOption/ListGroupsOption
  public static class Detail implements RestReadView<ChangeResource> {
    private final ChangeEditUtil editUtil;
    private final ChangeEditJson editJson;
    private final FileInfoJson fileInfoJson;
    private final Revisions revisions;

    private String base;
    private boolean list;
    private boolean downloadCommands;

    @Option(name = "--base", metaVar = "revision-id")
    public void setBase(String base) {
      this.base = base;
    }

    @Option(name = "--list")
    public void setList(boolean list) {
      this.list = list;
    }

    @Option(name = "--download-commands")
    public void setDownloadCommands(boolean downloadCommands) {
      this.downloadCommands = downloadCommands;
    }

    @Inject
    Detail(
        ChangeEditUtil editUtil,
        ChangeEditJson editJson,
        FileInfoJson fileInfoJson,
        Revisions revisions) {
      this.editJson = editJson;
      this.editUtil = editUtil;
      this.fileInfoJson = fileInfoJson;
      this.revisions = revisions;
    }

    @Override
    public Response<EditInfo> apply(ChangeResource rsrc)
        throws AuthException, IOException, ResourceNotFoundException, PermissionBackendException {
      Optional<ChangeEdit> edit = editUtil.byChange(rsrc.getNotes(), rsrc.getUser());
      if (!edit.isPresent()) {
        return Response.none();
      }

      EditInfo editInfo = editJson.toEditInfo(edit.get(), downloadCommands);
      if (list) {
        PatchSet basePatchSet = null;
        if (base != null) {
          RevisionResource baseResource = revisions.parse(rsrc, IdString.fromDecoded(base));
          basePatchSet = baseResource.getPatchSet();
        }
        try {
          editInfo.files =
              fileInfoJson.toFileInfoMap(
                  rsrc.getChange(), edit.get().getEditCommit(), basePatchSet);
        } catch (PatchListNotAvailableException e) {
          throw new ResourceNotFoundException(e.getMessage());
        }
      }
      return Response.ok(editInfo);
    }
  }

  /**
   * Post to edit collection resource. Two different operations are supported:
   *
   * <ul>
   *   <li>Create non existing change edit
   *   <li>Restore path in existing change edit
   * </ul>
   *
   * The combination of two operations in one request is supported.
   */
  @Singleton
  public static class Post
      implements RestCollectionModifyView<ChangeResource, ChangeEditResource, Post.Input> {
    public static class Input {
      public String restorePath;
      public String oldPath;
      public String newPath;
    }

    private final ChangeEditModifier editModifier;
    private final GitRepositoryManager repositoryManager;

    @Inject
    Post(ChangeEditModifier editModifier, GitRepositoryManager repositoryManager) {
      this.editModifier = editModifier;
      this.repositoryManager = repositoryManager;
    }

    @Override
    public Response<?> apply(ChangeResource resource, Post.Input input)
        throws AuthException, BadRequestException, IOException, ResourceConflictException,
            PermissionBackendException {
      Project.NameKey project = resource.getProject();
      try (Repository repository = repositoryManager.openRepository(project)) {
        if (isRestoreFile(input)) {
          editModifier.restoreFile(repository, resource.getNotes(), input.restorePath);
        } else if (isRenameFile(input)) {
          editModifier.renameFile(repository, resource.getNotes(), input.oldPath, input.newPath);
        } else {
          editModifier.createEdit(repository, resource.getNotes());
        }
      } catch (InvalidChangeOperationException e) {
        throw new ResourceConflictException(e.getMessage());
      }
      return Response.none();
    }

    private static boolean isRestoreFile(Input input) {
      return input != null && !Strings.isNullOrEmpty(input.restorePath);
    }

    private static boolean isRenameFile(Input input) {
      return input != null
          && !Strings.isNullOrEmpty(input.oldPath)
          && !Strings.isNullOrEmpty(input.newPath);
    }
  }

  /** Put handler that is activated when PUT request is called on collection element. */
  @Singleton
  public static class Put implements RestModifyView<ChangeEditResource, Put.Input> {
    public static class Input {
      @DefaultInput public RawInput content;
    }

    private final ChangeEditModifier editModifier;
    private final GitRepositoryManager repositoryManager;
    private final EditMessage editMessage;

    @Inject
    Put(
        ChangeEditModifier editModifier,
        GitRepositoryManager repositoryManager,
        EditMessage editMessage) {
      this.editModifier = editModifier;
      this.repositoryManager = repositoryManager;
      this.editMessage = editMessage;
    }

    @Override
    public Response<?> apply(ChangeEditResource rsrc, Input input)
        throws AuthException, ResourceConflictException, BadRequestException, IOException,
            PermissionBackendException, BadRequestException {
      return apply(rsrc.getChangeResource(), rsrc.getPath(), input.content);
    }

    public Response<?> apply(ChangeResource rsrc, String path, RawInput newContent)
        throws ResourceConflictException, AuthException, BadRequestException, IOException,
            PermissionBackendException, BadRequestException {
      if (Patch.COMMIT_MSG.equals(path)) {
        EditMessage.Input editCommitMessageInput = new EditMessage.Input();
        editCommitMessageInput.message =
            new String(ByteStreams.toByteArray(newContent.getInputStream()), UTF_8);
        return editMessage.apply(rsrc, editCommitMessageInput);
      }
      if (Strings.isNullOrEmpty(path) || path.charAt(0) == '/') {
        throw new ResourceConflictException("Invalid path: " + path);
      }

      try (Repository repository = repositoryManager.openRepository(rsrc.getProject())) {
        editModifier.modifyFile(repository, rsrc.getNotes(), path, newContent);
      } catch (InvalidChangeOperationException e) {
        throw new ResourceConflictException(e.getMessage());
      }
      return Response.none();
    }
  }

  /**
   * Handler to delete a file.
   *
   * <p>This deletes the file from the repository completely. This is not the same as reverting or
   * restoring a file to its previous contents.
   */
  @Singleton
  public static class DeleteContent implements RestModifyView<ChangeEditResource, Input> {

    private final ChangeEditModifier editModifier;
    private final GitRepositoryManager repositoryManager;

    @Inject
    DeleteContent(ChangeEditModifier editModifier, GitRepositoryManager repositoryManager) {
      this.editModifier = editModifier;
      this.repositoryManager = repositoryManager;
    }

    @Override
    public Response<?> apply(ChangeEditResource rsrc, Input input)
        throws AuthException, BadRequestException, ResourceConflictException, IOException,
            PermissionBackendException {
      return apply(rsrc.getChangeResource(), rsrc.getPath());
    }

    public Response<?> apply(ChangeResource rsrc, String filePath)
        throws AuthException, BadRequestException, IOException, ResourceConflictException,
            PermissionBackendException {
      try (Repository repository = repositoryManager.openRepository(rsrc.getProject())) {
        editModifier.deleteFile(repository, rsrc.getNotes(), filePath);
      } catch (InvalidChangeOperationException e) {
        throw new ResourceConflictException(e.getMessage());
      }
      return Response.none();
    }
  }

  public static class Get implements RestReadView<ChangeEditResource> {
    private final FileContentUtil fileContentUtil;
    private final ProjectCache projectCache;
    private final GetMessage getMessage;

    @Option(
        name = "--base",
        aliases = {"-b"},
        usage = "whether to load the content on the base revision instead of the change edit")
    private boolean base;

    @Inject
    Get(FileContentUtil fileContentUtil, ProjectCache projectCache, GetMessage getMessage) {
      this.fileContentUtil = fileContentUtil;
      this.projectCache = projectCache;
      this.getMessage = getMessage;
    }

    @Override
    public Response<BinaryResult> apply(ChangeEditResource rsrc) throws AuthException, IOException {
      try {
        if (Patch.COMMIT_MSG.equals(rsrc.getPath())) {
          return getMessage.apply(rsrc.getChangeResource());
        }

        ChangeEdit edit = rsrc.getChangeEdit();
        return Response.ok(
            fileContentUtil.getContent(
                projectCache.checkedGet(rsrc.getChangeResource().getProject()),
                base ? edit.getBasePatchSet().commitId() : edit.getEditCommit(),
                rsrc.getPath(),
                null));
      } catch (ResourceNotFoundException | BadRequestException e) {
        return Response.none();
      }
    }
  }

  @Singleton
  public static class GetMeta implements RestReadView<ChangeEditResource> {
    private final WebLinks webLinks;

    @Inject
    GetMeta(WebLinks webLinks) {
      this.webLinks = webLinks;
    }

    @Override
    public Response<FileInfo> apply(ChangeEditResource rsrc) {
      FileInfo r = new FileInfo();
      ChangeEdit edit = rsrc.getChangeEdit();
      Change change = edit.getChange();
      ImmutableList<DiffWebLinkInfo> links =
          webLinks.getDiffLinks(
              change.getProject().get(),
              change.getChangeId(),
              edit.getBasePatchSet().number(),
              edit.getBasePatchSet().refName(),
              rsrc.getPath(),
              0,
              edit.getRefName(),
              rsrc.getPath());
      r.webLinks = links.isEmpty() ? null : links;
      return Response.ok(r);
    }

    public static class FileInfo {
      public List<DiffWebLinkInfo> webLinks;
    }
  }

  @Singleton
  public static class EditMessage implements RestModifyView<ChangeResource, EditMessage.Input> {
    public static class Input {
      @DefaultInput public String message;
    }

    private final ChangeEditModifier editModifier;
    private final GitRepositoryManager repositoryManager;

    @Inject
    EditMessage(ChangeEditModifier editModifier, GitRepositoryManager repositoryManager) {
      this.editModifier = editModifier;
      this.repositoryManager = repositoryManager;
    }

    @Override
    public Response<Object> apply(ChangeResource rsrc, Input input)
        throws AuthException, IOException, BadRequestException, ResourceConflictException,
            PermissionBackendException {
      if (input == null || Strings.isNullOrEmpty(input.message)) {
        throw new BadRequestException("commit message must be provided");
      }

      Project.NameKey project = rsrc.getProject();
      try (Repository repository = repositoryManager.openRepository(project)) {
        editModifier.modifyMessage(repository, project, rsrc.getNotes(), input.message);
      } catch (UnchangedCommitMessageException e) {
        throw new ResourceConflictException(e.getMessage());
      }

      return Response.none();
    }
  }

  public static class GetMessage implements RestReadView<ChangeResource> {
    private final GitRepositoryManager repoManager;
    private final ChangeEditUtil editUtil;

    @Option(
        name = "--base",
        aliases = {"-b"},
        usage = "whether to load the message on the base revision instead of the change edit")
    private boolean base;

    @Inject
    GetMessage(GitRepositoryManager repoManager, ChangeEditUtil editUtil) {
      this.repoManager = repoManager;
      this.editUtil = editUtil;
    }

    @Override
    public Response<BinaryResult> apply(ChangeResource rsrc)
        throws AuthException, IOException, ResourceNotFoundException {
      Optional<ChangeEdit> edit = editUtil.byChange(rsrc.getNotes(), rsrc.getUser());
      String msg;
      if (edit.isPresent()) {
        if (base) {
          try (Repository repo = repoManager.openRepository(rsrc.getProject());
              RevWalk rw = new RevWalk(repo)) {
            RevCommit commit = rw.parseCommit(edit.get().getBasePatchSet().commitId());
            msg = commit.getFullMessage();
          }
        } else {
          msg = edit.get().getEditCommit().getFullMessage();
        }

        return Response.ok(
            BinaryResult.create(msg)
                .setContentType(FileContentUtil.TEXT_X_GERRIT_COMMIT_MESSAGE)
                .base64());
      }
      throw new ResourceNotFoundException();
    }
  }
}
