// 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 java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** 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"));

    List<String> patterns = new ArrayList<>();
    patterns.add(HTTP_URL_PATTERN.pattern());
    patterns.add(CHANGE_ID_PATTERN.pattern());

    for (String subsection : config.getSubsections(COMMENTLINK)) {
      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;
      }
      Pattern pattern;
      try {
        pattern = Pattern.compile(match);
      } catch (PatternSyntaxException ex) {
        log.warn("invalid commentlink." + subsection + ".match", ex);
        continue;
      }
      if (Strings.isNullOrEmpty(link)) {
        log.warn("invalid commentlink.%s.link", subsection);
        continue;
      }
      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");
      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;
  }
}
