// 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.server.config;

import com.google.gerrit.client.data.ApprovalType;
import com.google.gerrit.client.data.GerritConfig;
import com.google.gerrit.client.data.GitwebLink;
import com.google.gerrit.client.reviewdb.ApprovalCategory;
import com.google.gerrit.client.reviewdb.Project;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.rpc.Common;
import com.google.gerrit.server.ContactStore;
import com.google.gerrit.server.mail.EmailSender;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;

import org.spearce.jgit.lib.Config;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;

public class GerritConfigProvider implements Provider<GerritConfig> {
  private static boolean isIPv6(final InetAddress ip) {
    return ip instanceof Inet6Address
        && ip.getHostName().equals(ip.getHostAddress());
  }

  private final Config cfg;
  private final String canonicalWebUrl;
  private final AuthConfig authConfig;
  private final SchemaFactory<ReviewDb> schema;
  private final Project.NameKey wildProject;

  private SshInfo sshd;
  private EmailSender emailSender;
  private ContactStore contactStore;

  @Inject
  GerritConfigProvider(@GerritServerConfig final Config gsc,
      @CanonicalWebUrl @Nullable final String cwu, final AuthConfig ac,
      final SchemaFactory<ReviewDb> sf,
      @WildProjectName final Project.NameKey wp) {
    cfg = gsc;
    canonicalWebUrl = cwu;
    authConfig = ac;
    schema = sf;
    wildProject = wp;
  }

  @Inject(optional = true)
  void setSshd(final SshInfo d) {
    sshd = d;
  }

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

  @Inject(optional = true)
  void setContactStore(final ContactStore d) {
    contactStore = d;
  }

  private GerritConfig create() throws OrmException {
    final GerritConfig config = new GerritConfig();
    config.setCanonicalUrl(canonicalWebUrl);
    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.setAllowRegisterNewEmail(emailSender != null
        && emailSender.isEnabled());
    config.setLoginType(authConfig.getLoginType());
    config.setWildProject(wildProject);

    final String gitwebUrl = cfg.getString("gitweb", null, "url");
    if (gitwebUrl != null) {
      config.setGitwebLink(new GitwebLink(gitwebUrl));
    }

    final ReviewDb db = schema.open();
    try {
      for (final ApprovalCategory c : db.approvalCategories().all()) {
        config.add(new ApprovalType(c, db.approvalCategoryValues().byCategory(
            c.getId()).toList()));
      }
    } finally {
      db.close();
    }

    final InetSocketAddress addr = sshd != null ? sshd.getAddress() : null;
    if (addr != null) {
      final InetAddress ip = addr.getAddress();
      String host;
      if (ip != null && ip.isAnyLocalAddress()) {
        host = "";
      } else if (isIPv6(ip)) {
        host = "[" + addr.getHostName() + "]";
      } else {
        host = addr.getHostName();
      }
      if (addr.getPort() != 22) {
        host += ":" + addr.getPort();
      }
      config.setSshdAddress(host);
    }

    Common.setGerritConfig(config);
    return config;
  }

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

@@ -1905,17 +1905,16 @@
 roject;%0A
-%0A
   privat
@@ -1915,16 +1915,22 @@
 private 
+final 
 SshInfo 
@@ -1932,18 +1932,22 @@
 Info ssh
-d;
+Info;%0A
 %0A  priva
@@ -2242,20 +2242,38 @@
 meKey wp
+, final SshInfo si
 ) %7B%0A
-
     cfg 
@@ -2344,16 +2344,34 @@
 a = sf;%0A
+    sshInfo = si;%0A
     wild
@@ -2393,88 +2393,8 @@
  %7D%0A%0A
-  @Inject(optional = true)%0A  void setSshd(final SshInfo d) %7B%0A    sshd = d;%0A  %7D%0A%0A
   @I
@@ -3761,21 +3761,32 @@
 s addr =
- sshd
+%0A        sshInfo
  != null
@@ -3791,17 +3791,20 @@
 ll ? ssh
-d
+Info
 .getAddr

Fix sshdAddress in GerritConfig object sent to clients