// 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.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

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

    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,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;
  }
}
