// Copyright (C) 2013 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.ssh;

import com.google.common.collect.Lists;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.util.SocketUtil;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;

import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Arrays;
import java.util.List;

public class SshAddressesModule extends AbstractModule {
  private static final Logger log =
      LoggerFactory.getLogger(SshAddressesModule.class);

  public static final int DEFAULT_PORT = 29418;
  public static final int IANA_SSH_PORT = 22;

  @Override
  protected void configure() {
  }

  @Provides
  @Singleton
  @SshListenAddresses
  List<SocketAddress> getListenAddresses(@GerritServerConfig Config cfg) {
    List<SocketAddress> listen = Lists.newArrayListWithExpectedSize(2);
    String[] want = cfg.getStringList("sshd", null, "listenaddress");
    if (want == null || want.length == 0) {
      listen.add(new InetSocketAddress(DEFAULT_PORT));
      return listen;
    }

    if (want.length == 1 && isOff(want[0])) {
      return listen;
    }

    for (final String desc : want) {
      try {
        listen.add(SocketUtil.resolve(desc, DEFAULT_PORT));
      } catch (IllegalArgumentException e) {
        log.error("Bad sshd.listenaddress: " + desc + ": " + e.getMessage());
      }
    }
    return listen;
  }

  private static boolean isOff(String listenHostname) {
    return "off".equalsIgnoreCase(listenHostname)
        || "none".equalsIgnoreCase(listenHostname)
        || "no".equalsIgnoreCase(listenHostname);
  }

  @Provides
  @Singleton
  @SshAdvertisedAddresses
  List<String> getAdvertisedAddresses(@GerritServerConfig Config cfg,
      @SshListenAddresses List<SocketAddress> listen) {
    String[] want = cfg.getStringList("sshd", null, "advertisedaddress");
    if (want.length > 0) {
      return Arrays.asList(want);
    }
    List<InetSocketAddress> pub = Lists.newArrayList();
    List<InetSocketAddress> local = Lists.newArrayList();

    for (SocketAddress addr : listen) {
      if (addr instanceof InetSocketAddress) {
        InetSocketAddress inetAddr = (InetSocketAddress) addr;
        if (inetAddr.getAddress().isLoopbackAddress()) {
          local.add(inetAddr);
        } else {
          pub.add(inetAddr);
        }
      }
    }
    if (pub.isEmpty()) {
      pub = local;
    }
    List<String> adv = Lists.newArrayListWithCapacity(pub.size());
    for (InetSocketAddress addr : pub) {
      adv.add(SocketUtil.format(addr, IANA_SSH_PORT));
    }
    return adv;
  }
}
