// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.gitiles;

import static com.google.common.base.Preconditions.checkState;
import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.template.soy.data.SoyListData;
import com.google.template.soy.data.SoyMapData;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.util.RawParseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import prettify.parser.Prettify;
import syntaxhighlight.ParseResult;

/** Soy data converter for git blobs. */
public class BlobSoyData {
  private static final Logger log = LoggerFactory.getLogger(BlobSoyData.class);

  /**
   * Maximum number of bytes to load from a supposed text file for display. Files larger than this
   * will be displayed as binary files, even if the contents was text. For example really big XML
   * files may be above this limit and will get displayed as binary.
   */
  @VisibleForTesting static final int MAX_FILE_SIZE = 10 << 20;

  /**
   * Maximum number of lines to be displayed. Files larger than this will be displayed as binary
   * files, even on a text content. For example really big XML files may be above this limit and
   * will get displayed as binary.
   */
  private static final int MAX_LINE_COUNT = 50000;

  private final GitilesView view;
  private final ObjectReader reader;

  public BlobSoyData(ObjectReader reader, GitilesView view) {
    this.reader = reader;
    this.view = view;
  }

  public Map<String, Object> toSoyData(ObjectId blobId) throws MissingObjectException, IOException {
    return toSoyData(null, blobId);
  }

  public Map<String, Object> toSoyData(String path, ObjectId blobId)
      throws MissingObjectException, IOException {
    Map<String, Object> data = Maps.newHashMapWithExpectedSize(4);
    data.put("sha", ObjectId.toString(blobId));

    ObjectLoader loader = reader.open(blobId, Constants.OBJ_BLOB);
    String content;
    try {
      byte[] raw = loader.getCachedBytes(MAX_FILE_SIZE);
      content =
          (raw.length < MAX_FILE_SIZE && !RawText.isBinary(raw)) ? RawParseUtils.decode(raw) : null;
      if (isContentTooLargeForDisplay(content)) {
        content = null;
      }
    } catch (LargeObjectException.OutOfMemory e) {
      throw e;
    } catch (LargeObjectException e) {
      content = null;
    }

    if (content != null) {
      data.put("lines", prettify(path, content));
      if (path != null && path.endsWith(".md")) {
        data.put("docUrl", GitilesView.doc().copyFrom(view).toUrl());
      }
    } else {
      data.put("lines", null);
      data.put("size", Long.toString(loader.getSize()));
    }
    if (path != null && view.getRevision().getPeeledType() == OBJ_COMMIT) {
      data.put("fileUrl", GitilesView.path().copyFrom(view).toUrl());
      data.put("logUrl", GitilesView.log().copyFrom(view).toUrl());
      data.put("blameUrl", GitilesView.blame().copyFrom(view).toUrl());
    }
    return data;
  }

  private SoyListData prettify(String path, String content) {
    List<ParseResult> results = parse(path, content);
    SoyListData lines = new SoyListData();
    SoyListData line = new SoyListData();
    lines.add(line);

    int last = 0;
    for (ParseResult r : results) {
      checkState(
          r.getOffset() >= last,
          "out-of-order ParseResult, expected %s >= %s",
          r.getOffset(),
          last);
      writeResult(lines, null, content, last, r.getOffset());
      last = r.getOffset() + r.getLength();
      writeResult(lines, r.getStyleKeysString(), content, r.getOffset(), last);
    }
    if (last < content.length()) {
      writeResult(lines, null, content, last, content.length());
    }
    return lines;
  }

  private List<ParseResult> parse(String path, String content) {
    String lang = extension(path, content);
    try {
      return ThreadSafePrettifyParser.INSTANCE.parse(lang, content);
    } catch (StackOverflowError e) {
      // TODO(dborowitz): Aaagh. Make prettify use RE2. Or replace it something
      // else. Or something.
      log.warn("StackOverflowError prettifying {}", view.toUrl());
      return ImmutableList.of(
          new ParseResult(0, content.length(), ImmutableList.of(Prettify.PR_PLAIN)));
    }
  }

  private static void writeResult(SoyListData lines, String classes, String s, int start, int end) {
    SoyListData line = lines.getListData(lines.length() - 1);
    while (true) {
      int nl = nextLineBreak(s, start, end);
      if (nl < 0) {
        break;
      }
      addSpan(line, classes, s, start, nl);

      start = nl + 1;
      if (start == s.length()) {
        return;
      }
      line = new SoyListData();
      lines.add(line);
    }
    addSpan(line, classes, s, start, end);
  }

  private static void addSpan(SoyListData line, String classes, String s, int start, int end) {
    if (end - start > 0) {
      if (Strings.isNullOrEmpty(classes)) {
        classes = Prettify.PR_PLAIN;
      }
      line.add(new SoyMapData("classes", classes, "text", s.substring(start, end)));
    }
  }

  private static int nextLineBreak(String s, int start, int end) {
    int n = s.indexOf('\n', start);
    return n < end ? n : -1;
  }

  private static String extension(String path, String content) {
    if (content.startsWith("#!/bin/sh") || content.startsWith("#!/bin/bash")) {
      return "sh";
    } else if (content.startsWith("#!/usr/bin/perl")) {
      return "pl";
    } else if (content.startsWith("#!/usr/bin/python")) {
      return "py";
    } else if (path == null) {
      return null;
    }

    int slash = path.lastIndexOf('/');
    int dot = path.lastIndexOf('.');
    String ext = ((0 < dot) && (slash < dot)) ? path.substring(dot + 1) : null;
    if ("txt".equalsIgnoreCase(ext)) {
      return null;
    } else if ("mk".equalsIgnoreCase(ext)) {
      return "sh";
    } else if ("Makefile".equalsIgnoreCase(path)
        || ((0 < slash) && "Makefile".equalsIgnoreCase(path.substring(slash + 1)))) {
      return "sh";
    } else {
      return ext;
    }
  }

  private static boolean isContentTooLargeForDisplay(String content) {
    if (content == null) {
      return false;
    }

    int lines = 0;
    int nl = -1;
    while (true) {
      nl = nextLineBreak(content, nl + 1, content.length());
      if (nl < 0) {
        return false;
      } else if (++lines == MAX_LINE_COUNT) {
        return true;
      }
    }
  }
}
