// 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.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.io.BaseEncoding;
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;

  /** Allowed image extensions to render */
  private static final ImmutableSet<String> ALLOWED_IMAGE_TYPES =
      ImmutableSet.of(
          "image/gif", "image/jpeg", "image/jpg", "image/png", "image/tiff", "image/webp");

  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;
    String imageBlob;
    try {
      byte[] raw = loader.getCachedBytes(MAX_FILE_SIZE);

      String type = MimeTypes.getMimeType(path);
      if (ALLOWED_IMAGE_TYPES.contains(type) && raw.length < MAX_FILE_SIZE) {
        imageBlob = "data:" + type + ";base64," + BaseEncoding.base64().encode(raw);
      } else {
        imageBlob = null;
      }
      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;
      imageBlob = 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());
      if (imageBlob != null) {
        data.put("imgBlob", imageBlob);
      }
    }
    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 ("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;
      }
    }
  }
}
