// 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.checkNotNull;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;

import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

/** Linkifier for blocks of text such as commit message descriptions. */
public class Linkifier {
  private static final Logger log = LoggerFactory.getLogger(Linkifier.class);

  private static final String COMMENTLINK = "commentlink";
  private static final Pattern HTTP_URL_PATTERN;
  private static final Pattern CHANGE_ID_PATTERN;

  static {
    // HTTP URL regex adapted from com.google.gwtexpui.safehtml.client.SafeHtml.
    String part = "(?:" +
        "[a-zA-Z0-9$_.+!*',%;:@=?#/~<>-]" +
        "|&(?!lt;|gt;)" +
        ")";
    String httpUrl = "https?://" +
        part + "{2,}" +
        "(?:[(]" + part + "*" + "[)])*" +
        part + "*";
    HTTP_URL_PATTERN = Pattern.compile(httpUrl);
    CHANGE_ID_PATTERN = Pattern.compile("(\\bI[0-9a-f]{8,40}\\b)");
  }

  private final GitilesUrls urls;
  private final List<CommentLinkInfo> commentLinks;
  private final Pattern allPattern;

  public Linkifier(GitilesUrls urls, Config config) {
    this.urls = checkNotNull(urls, "urls");

    List<CommentLinkInfo> list = new ArrayList<>();
    list.add(new CommentLinkInfo(HTTP_URL_PATTERN, "$0"));
    Set<String> subsections = config.getSubsections(COMMENTLINK);

    List<String> patterns = new ArrayList<>();

    patterns.add(HTTP_URL_PATTERN.pattern());
    patterns.add(CHANGE_ID_PATTERN.pattern());

    for (String subsection : subsections) {
      String match = config.getString("commentlink", subsection, "match");
      String link = config.getString("commentlink", subsection, "link");
      String html = config.getString("commentlink", subsection, "html");
      if (html != null) {
        log.warn("Beware: html in commentlinks is unsupported in gitiles; "
               + "Did you copy it from a gerrit config?");
      }
      if (Strings.isNullOrEmpty(match)) {
        log.warn("invalid commentlink.%s.match", subsection);
        continue;
      }
      if (Strings.isNullOrEmpty(link)) {
        log.warn("invalid commentlink.%s.link", subsection);
        continue;
      }
      Pattern pattern = Pattern.compile(match);
      list.add(new CommentLinkInfo(pattern, link));
      patterns.add(match);
    }
    this.commentLinks = Collections.unmodifiableList(list);
    allPattern = Pattern.compile(Joiner.on('|').join(patterns));
  }

  public List<Map<String, String>> linkify(HttpServletRequest req, String message) {

    List<CommentLinkInfo> operationalCommentLinks = new ArrayList<>(commentLinks);
    // Because we're relying on 'req' as a dynamic parameter, we need to construct
    // the CommentLinkInfo for ChangeIds on the fly.
    String baseGerritUrl = urls.getBaseGerritUrl(req);

    if (baseGerritUrl != null) {
      CommentLinkInfo changeIds =
          new CommentLinkInfo(CHANGE_ID_PATTERN, baseGerritUrl + "#/q/$0,n,z");
      operationalCommentLinks.add(changeIds);
    }

    List<Map<String, String>> parsed = Lists.newArrayList();
    parsed.add(ImmutableMap.of("text", message));

    for (int index = 0; index < parsed.size(); index++) {
      if (parsed.get(index).get("url") != null) {
        continue;
      }
      Matcher m = allPattern.matcher(parsed.get(index).get("text"));
      if (!m.find()) {
        continue;
      }

      for (CommentLinkInfo cli : operationalCommentLinks) {
        // No need to apply more rules if this is already a link.
        if (parsed.get(index).get("url") != null) {
          break;
        }
        String text = parsed.get(index).get("text");
        parsed.remove(index);
        parsed.addAll(index, cli.linkify(text));
      }
    }
    return parsed;
  }
}
