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

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

import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;

import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.kohsuke.args4j.Option;

import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class GetPatch implements RestReadView<RevisionResource> {
  private final GitRepositoryManager repoManager;

  @Option(name = "--zip")
  private boolean zip;

  @Option(name = "--download")
  private boolean download;

  @Inject
  GetPatch(GitRepositoryManager repoManager) {
    this.repoManager = repoManager;
  }

  @Override
  public BinaryResult apply(RevisionResource rsrc)
      throws ResourceConflictException, IOException {
    Project.NameKey project = rsrc.getControl().getProject().getNameKey();
    final Repository repo = repoManager.openRepository(project);
    boolean close = true;
    try {
      final RevWalk rw = new RevWalk(repo);
      try {
        final RevCommit commit =
            rw.parseCommit(ObjectId.fromString(rsrc.getPatchSet()
                .getRevision().get()));
        RevCommit[] parents = commit.getParents();
        if (parents.length > 1) {
          throw new ResourceConflictException(
              "Revision has more than 1 parent.");
        } else if (parents.length == 0) {
          throw new ResourceConflictException("Revision has no parent.");
        }
        final RevCommit base = parents[0];
        rw.parseBody(base);

        BinaryResult bin = new BinaryResult() {
          @Override
          public void writeTo(OutputStream out) throws IOException {
            if (zip) {
              ZipOutputStream zos = new ZipOutputStream(out);
              ZipEntry e = new ZipEntry(fileName(rw, commit));
              e.setTime(commit.getCommitTime() * 1000L);
              zos.putNextEntry(e);
              format(zos);
              zos.closeEntry();
              zos.finish();
            } else {
              format(out);
            }
          }

          private void format(OutputStream out) throws IOException {
            out.write(formatEmailHeader(commit).getBytes(UTF_8));
            DiffFormatter fmt = new DiffFormatter(out);
            fmt.setRepository(repo);
            fmt.format(base.getTree(), commit.getTree());
            fmt.flush();
          }

          @Override
          public void close() throws IOException {
            rw.release();
            repo.close();
          }
        };

        if (zip) {
          bin.disableGzip()
             .setContentType("application/zip")
             .setAttachmentName(fileName(rw, commit) + ".zip");
        } else {
          bin.base64()
             .setContentType("application/mbox")
             .setAttachmentName(download
                 ? fileName(rw, commit) + ".base64"
                 : null);
        }

        close = false;
        return bin;
      } finally {
        if (close) {
          rw.release();
        }
      }
    } finally {
      if (close) {
        repo.close();
      }
    }
  }

  private static String formatEmailHeader(RevCommit commit) {
    StringBuilder b = new StringBuilder();
    PersonIdent author = commit.getAuthorIdent();
    String subject = commit.getShortMessage();
    String msg = commit.getFullMessage().substring(subject.length());
    if (msg.startsWith("\n\n")) {
      msg = msg.substring(2);
    }
    b.append("From ").append(commit.getName())
     .append(' ')
     .append("Mon Sep 17 00:00:00 2001\n")
     .append("From: ").append(author.getName())
     .append(" <").append(author.getEmailAddress()).append(">\n")
     .append("Date: ").append(formatDate(author)).append('\n')
     .append("Subject: [PATCH] ").append(subject).append('\n')
     .append('\n')
     .append(msg);
    if (!msg.endsWith("\n")) {
     b.append('\n');
    }
    return b.append("---\n\n").toString();
  }

  private static String formatDate(PersonIdent author) {
    SimpleDateFormat df = new SimpleDateFormat(
        "EEE, dd MMM yyyy HH:mm:ss Z",
        Locale.US);
    df.setCalendar(Calendar.getInstance(author.getTimeZone(), Locale.US));
    return df.format(author.getWhen());
  }

  private static String fileName(RevWalk rw, RevCommit commit)
      throws IOException {
    AbbreviatedObjectId id = rw.getObjectReader().abbreviate(commit, 8);
    return id.name() + ".diff";
  }
}
