// 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) {
        String msg = "invalid commentlink." + subsection + ".match";
        if (log.isDebugEnabled()) {
          log.debug(msg, ex);
        } else {
          log.warn(msg + ": " + ex.getMessage());
        }
        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;
  }
}
