// Copyright (C) 2009 The Android Open Source Project
//
// 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.gerrit.httpd;

import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.GerritConfig;
import com.google.gerrit.common.data.GitwebLink;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.WildProjectName;
import com.google.gerrit.server.contact.ContactStore;
import com.google.gerrit.server.mail.EmailSender;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gwtexpui.safehtml.client.RegexFindReplace;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;

import org.eclipse.jgit.lib.Config;

import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.servlet.ServletContext;

class GerritConfigProvider implements Provider<GerritConfig> {
  private final Realm realm;
  private final Config cfg;
  private final AuthConfig authConfig;
  private final GitWebConfig gitWebConfig;
  private final Project.NameKey wildProject;
  private final SshInfo sshInfo;
  private final ApprovalTypes approvalTypes;

  private EmailSender emailSender;
  private final ContactStore contactStore;
  private final ServletContext servletContext;

  @Inject
  GerritConfigProvider(final Realm r, @GerritServerConfig final Config gsc,
      final AuthConfig ac, final GitWebConfig gwc,
      @WildProjectName final Project.NameKey wp, final SshInfo si,
      final ApprovalTypes at, final ContactStore cs, final ServletContext sc) {
    realm = r;
    cfg = gsc;
    authConfig = ac;
    gitWebConfig = gwc;
    sshInfo = si;
    wildProject = wp;
    approvalTypes = at;
    contactStore = cs;
    servletContext = sc;
  }

  @Inject(optional = true)
  void setEmailSender(final EmailSender d) {
    emailSender = d;
  }

  private GerritConfig create() throws MalformedURLException {
    final GerritConfig config = new GerritConfig();
    switch (authConfig.getAuthType()) {
      case OPENID:
        config.setAllowedOpenIDs(authConfig.getAllowedOpenIDs());
        break;

      case LDAP:
      case LDAP_BIND:
        config.setRegisterUrl(cfg.getString("auth", null, "registerurl"));
        break;
    }
    config.setUseContributorAgreements(cfg.getBoolean("auth",
        "contributoragreements", false));
    config.setGitDaemonUrl(cfg.getString("gerrit", null, "canonicalgiturl"));
    config.setUseRepoDownload(cfg.getBoolean("repo", null,
        "showdownloadcommand", false));
    config.setUseContactInfo(contactStore != null && contactStore.isEnabled());
    config.setAuthType(authConfig.getAuthType());
    config.setWildProject(wildProject);
    config.setApprovalTypes(approvalTypes);
    config.setDocumentationAvailable(servletContext
        .getResource("/Documentation/index.html") != null);

    final Set<Account.FieldName> fields = new HashSet<Account.FieldName>();
    for (final Account.FieldName n : Account.FieldName.values()) {
      if (realm.allowsEdit(n)) {
        fields.add(n);
      }
    }
    if (emailSender != null && emailSender.isEnabled()) {
      fields.add(Account.FieldName.REGISTER_NEW_EMAIL);
    }
    config.setEditableAccountFields(fields);

    if (gitWebConfig.getUrl() != null) {
      config.setGitwebLink(new GitwebLink(gitWebConfig.getUrl(), gitWebConfig
          .getGitWebType()));
    }

    if (sshInfo != null && !sshInfo.getHostKeys().isEmpty()) {
      config.setSshdAddress(sshInfo.getHostKeys().get(0).getHost());
    }

    List<RegexFindReplace> links = new ArrayList<RegexFindReplace>();
    for (String name : cfg.getSubsections("commentlink")) {
      String match = cfg.getString("commentlink", name, "match");

      // Unfortunately this validation isn't entirely complete. Clients
      // can have exceptions trying to evaluate the pattern if they don't
      // support a token used, even if the server does support the token.
      //
      // At the minimum, we can trap problems related to unmatched groups.
      try {
        Pattern.compile(match);
      } catch (PatternSyntaxException e) {
        throw new ProvisionException("Invalid pattern \"" + match
            + "\" in commentlink." + name + ".match: " + e.getMessage());
      }

      String link = cfg.getString("commentlink", name, "link");
      String html = cfg.getString("commentlink", name, "html");
      if (html == null || html.isEmpty()) {
        html = "<a href=\"" + link + "\">$&</a>";
      }
      links.add(new RegexFindReplace(match, html));
    }
    config.setCommentLinks(links);

    config.setBackgroundColor(getThemeColor("backgroundColor", "#FFFFFF"));
    config.setTextColor(getThemeColor("textColor", "#000000"));
    config.setTrimColor(getThemeColor("trimColor", "#D4E9A9"));
    config.setSelectionColor(getThemeColor("selectionColor", "#FFFFCC"));

    config
        .setTopMenuColor(getThemeColor("topMenuColor", config.getTrimColor()));

    return config;
  }

  private String getThemeColor(String name, String defaultValue) {
    String v = cfg.getString("theme", null, name);
    if (v == null || v.isEmpty()) {
      v = defaultValue;
    }
    if (!v.startsWith("#") && v.matches("^[0-9a-fA-F]{2,6}$")) {
      v = "#" + v;
    }
    return v;
  }

  @Override
  public GerritConfig get() {
    try {
      return create();
    } catch (MalformedURLException e) {
      throw new ProvisionException("Cannot create GerritConfig instance", e);
    }
  }
}
