// Copyright (C) 2019 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.diff;

import static com.google.common.base.Preconditions.checkState;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.data.PatchScript;
import com.google.gerrit.common.data.PatchScript.DisplayMethod;
import com.google.gerrit.common.data.PatchScript.PatchScriptFileInfo;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.extensions.common.ChangeType;
import com.google.gerrit.extensions.common.DiffInfo;
import com.google.gerrit.extensions.common.DiffInfo.ContentEntry;
import com.google.gerrit.extensions.common.DiffInfo.FileMeta;
import com.google.gerrit.extensions.common.DiffInfo.IntraLineStatus;
import com.google.gerrit.extensions.common.DiffWebLinkInfo;
import com.google.gerrit.extensions.common.WebLinkInfo;
import com.google.gerrit.jgit.diff.ReplaceEdit;
import com.google.gerrit.prettify.common.SparseFileContent;
import com.google.gerrit.server.change.FileContentUtil;
import com.google.gerrit.server.project.ProjectState;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jgit.diff.Edit;

/** Creates and fills a new {@link DiffInfo} object based on diff between files. */
public class DiffInfoCreator {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final ImmutableMap<Patch.ChangeType, ChangeType> CHANGE_TYPE =
      Maps.immutableEnumMap(
          new ImmutableMap.Builder<Patch.ChangeType, ChangeType>()
              .put(Patch.ChangeType.ADDED, ChangeType.ADDED)
              .put(Patch.ChangeType.MODIFIED, ChangeType.MODIFIED)
              .put(Patch.ChangeType.DELETED, ChangeType.DELETED)
              .put(Patch.ChangeType.RENAMED, ChangeType.RENAMED)
              .put(Patch.ChangeType.COPIED, ChangeType.COPIED)
              .put(Patch.ChangeType.REWRITE, ChangeType.REWRITE)
              .build());

  private final DiffWebLinksProvider webLinksProvider;
  private final boolean intraline;
  private final ProjectState state;

  public DiffInfoCreator(
      ProjectState state, DiffWebLinksProvider webLinksProvider, boolean intraline) {
    this.webLinksProvider = webLinksProvider;
    this.state = state;
    this.intraline = intraline;
  }

  /* Returns the {@link DiffInfo} to display for end-users */
  public DiffInfo create(PatchScript ps, DiffSide sideA, DiffSide sideB) {
    DiffInfo result = new DiffInfo();

    ImmutableList<DiffWebLinkInfo> links = webLinksProvider.getDiffLinks();
    result.webLinks = links.isEmpty() ? null : links;
    ImmutableList<WebLinkInfo> editLinks = webLinksProvider.getEditWebLinks();
    result.editWebLinks = editLinks.isEmpty() ? null : editLinks;

    if (ps.isBinary()) {
      result.binary = true;
    }
    result.metaA = createFileMeta(sideA).orElse(null);
    result.metaB = createFileMeta(sideB).orElse(null);

    if (intraline) {
      if (ps.hasIntralineTimeout()) {
        result.intralineStatus = IntraLineStatus.TIMEOUT;
      } else if (ps.hasIntralineFailure()) {
        result.intralineStatus = IntraLineStatus.FAILURE;
      } else {
        result.intralineStatus = IntraLineStatus.OK;
      }
      logger.atFine().log("intralineStatus = %s", result.intralineStatus);
    }

    result.changeType = CHANGE_TYPE.get(ps.getChangeType());
    logger.atFine().log("changeType = %s", result.changeType);
    if (result.changeType == null) {
      throw new IllegalStateException("unknown change type: " + ps.getChangeType());
    }

    if (ps.getPatchHeader().size() > 0) {
      result.diffHeader = ps.getPatchHeader();
    }
    result.content = calculateDiffContentEntries(ps);
    return result;
  }

  private static List<ContentEntry> calculateDiffContentEntries(PatchScript ps) {
    ContentCollector contentCollector = new ContentCollector(ps);
    Set<Edit> editsDueToRebase = ps.getEditsDueToRebase();
    for (Edit edit : ps.getEdits()) {
      logger.atFine().log("next edit = %s", edit);

      if (edit.getType() == Edit.Type.EMPTY) {
        logger.atFine().log("skip empty edit");
        continue;
      }
      contentCollector.addCommon(edit.getBeginA());

      checkState(
          contentCollector.nextA == edit.getBeginA(),
          "nextA = %s; want %s",
          contentCollector.nextA,
          edit.getBeginA());
      checkState(
          contentCollector.nextB == edit.getBeginB(),
          "nextB = %s; want %s",
          contentCollector.nextB,
          edit.getBeginB());
      switch (edit.getType()) {
        case DELETE:
        case INSERT:
        case REPLACE:
          List<Edit> internalEdit =
              edit instanceof ReplaceEdit ? ((ReplaceEdit) edit).getInternalEdits() : null;
          boolean dueToRebase = editsDueToRebase.contains(edit);
          contentCollector.addDiff(edit.getEndA(), edit.getEndB(), internalEdit, dueToRebase);
          break;
        case EMPTY:
        default:
          throw new IllegalStateException();
      }
    }
    contentCollector.addCommon(ps.getA().getSize());

    return contentCollector.lines;
  }

  private Optional<FileMeta> createFileMeta(DiffSide side) {
    PatchScriptFileInfo fileInfo = side.fileInfo();
    if (fileInfo.displayMethod == DisplayMethod.NONE) {
      return Optional.empty();
    }
    FileMeta result = new FileMeta();
    result.name = side.fileName();
    result.contentType =
        FileContentUtil.resolveContentType(
            state, side.fileName(), fileInfo.mode, fileInfo.mimeType);
    result.lines = fileInfo.content.getSize();
    ImmutableList<WebLinkInfo> fileLinks = webLinksProvider.getFileWebLinks(side.type());
    result.webLinks = fileLinks.isEmpty() ? null : fileLinks;
    result.commitId = fileInfo.commitId;
    return Optional.of(result);
  }

  private static class ContentCollector {

    private final List<ContentEntry> lines;
    private final SparseFileContent.Accessor fileA;
    private final SparseFileContent.Accessor fileB;
    private final boolean ignoreWS;

    private int nextA;
    private int nextB;

    ContentCollector(PatchScript ps) {
      lines = Lists.newArrayListWithExpectedSize(ps.getEdits().size() + 2);
      fileA = ps.getA().createAccessor();
      fileB = ps.getB().createAccessor();
      ignoreWS = ps.isIgnoreWhitespace();
    }

    void addCommon(int end) {
      logger.atFine().log("addCommon: end = %d", end);

      end = Math.min(end, fileA.getSize());
      logger.atFine().log("end = %d", end);

      if (nextA >= end) {
        logger.atFine().log("nextA >= end: nextA = %d, end = %d", nextA, end);
        return;
      }

      while (nextA < end) {
        logger.atFine().log("nextA < end: nextA = %d, end = %d", nextA, end);

        if (!fileA.contains(nextA)) {
          logger.atFine().log("fileA does not contain nextA: nextA = %d", nextA);

          int endRegion = Math.min(end, nextA == 0 ? fileA.first() : fileA.next(nextA - 1));
          int len = endRegion - nextA;
          entry().skip = len;
          nextA = endRegion;
          nextB += len;

          logger.atFine().log("setting: nextA = %d, nextB = %d", nextA, nextB);
          continue;
        }

        ContentEntry e = null;
        for (int i = nextA; i == nextA && i < end; i = fileA.next(i), nextA++, nextB++) {
          if (ignoreWS && fileB.contains(nextB)) {
            if (e == null || e.common == null) {
              logger.atFine().log("create new common entry: nextA = %d, nextB = %d", nextA, nextB);
              e = entry();
              e.a = Lists.newArrayListWithCapacity(end - nextA);
              e.b = Lists.newArrayListWithCapacity(end - nextA);
              e.common = true;
            }
            e.a.add(fileA.get(nextA));
            e.b.add(fileB.get(nextB));
          } else {
            if (e == null || e.common != null) {
              logger.atFine().log(
                  "create new non-common entry: nextA = %d, nextB = %d", nextA, nextB);
              e = entry();
              e.ab = Lists.newArrayListWithCapacity(end - nextA);
            }
            e.ab.add(fileA.get(nextA));
          }
        }
      }
    }

    void addDiff(int endA, int endB, List<Edit> internalEdit, boolean dueToRebase) {
      logger.atFine().log(
          "addDiff: endA = %d, endB = %d, numberOfInternalEdits = %d, dueToRebase = %s",
          endA, endB, internalEdit != null ? internalEdit.size() : 0, dueToRebase);

      int lenA = endA - nextA;
      int lenB = endB - nextB;
      logger.atFine().log("lenA = %d, lenB = %d", lenA, lenB);
      checkState(lenA > 0 || lenB > 0);

      logger.atFine().log("create non-common entry");
      ContentEntry e = entry();
      if (lenA > 0) {
        logger.atFine().log("lenA > 0: lenA = %d", lenA);
        e.a = Lists.newArrayListWithCapacity(lenA);
        for (; nextA < endA; nextA++) {
          e.a.add(fileA.get(nextA));
        }
      }
      if (lenB > 0) {
        logger.atFine().log("lenB > 0: lenB = %d", lenB);
        e.b = Lists.newArrayListWithCapacity(lenB);
        for (; nextB < endB; nextB++) {
          e.b.add(fileB.get(nextB));
        }
      }
      if (internalEdit != null && !internalEdit.isEmpty()) {
        logger.atFine().log("processing internal edits");

        e.editA = Lists.newArrayListWithCapacity(internalEdit.size() * 2);
        e.editB = Lists.newArrayListWithCapacity(internalEdit.size() * 2);
        int lastA = 0;
        int lastB = 0;
        for (Edit edit : internalEdit) {
          logger.atFine().log("internal edit = %s", edit);

          if (edit.getBeginA() != edit.getEndA()) {
            logger.atFine().log(
                "edit.getBeginA() != edit.getEndA(): edit.getBeginA() = %d, edit.getEndA() = %d",
                edit.getBeginA(), edit.getEndA());
            e.editA.add(
                ImmutableList.of(edit.getBeginA() - lastA, edit.getEndA() - edit.getBeginA()));
            lastA = edit.getEndA();
            logger.atFine().log("lastA = %d", lastA);
          }
          if (edit.getBeginB() != edit.getEndB()) {
            logger.atFine().log(
                "edit.getBeginB() != edit.getEndB(): edit.getBeginB() = %d, edit.getEndB() = %d",
                edit.getBeginB(), edit.getEndB());
            e.editB.add(
                ImmutableList.of(edit.getBeginB() - lastB, edit.getEndB() - edit.getBeginB()));
            lastB = edit.getEndB();
            logger.atFine().log("lastB = %d", lastB);
          }
        }
      }
      e.dueToRebase = dueToRebase ? true : null;
    }

    private ContentEntry entry() {
      ContentEntry e = new ContentEntry();
      lines.add(e);
      return e;
    }
  }
}
