// 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.pgm.init.api;

import static com.google.gerrit.common.FileUtil.modified;

import com.google.common.io.ByteStreams;
import com.google.gerrit.common.Die;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Arrays;
import org.eclipse.jgit.internal.storage.file.LockFile;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.SystemReader;

/** Utility functions to help initialize a site. */
public class InitUtil {
  public static Die die(String why) {
    return new Die(why);
  }

  public static Die die(String why, Throwable cause) {
    return new Die(why, cause);
  }

  public static void savePublic(FileBasedConfig sec) throws IOException {
    if (modified(sec)) {
      sec.save();
    }
  }

  public static void mkdir(File file) {
    mkdir(file.toPath());
  }

  public static void mkdir(Path path) {
    if (Files.isDirectory(path)) {
      return;
    }
    try {
      Files.createDirectory(path);
    } catch (IOException e) {
      throw die("Cannot make directory " + path, e);
    }
  }

  public static String version() {
    return com.google.gerrit.common.Version.getVersion();
  }

  public static String username() {
    return System.getProperty("user.name");
  }

  public static String hostname() {
    return SystemReader.getInstance().getHostname();
  }

  public static boolean isLocal(String hostname) {
    try {
      return InetAddress.getByName(hostname).isLoopbackAddress();
    } catch (UnknownHostException e) {
      return false;
    }
  }

  public static String dnOf(String name) {
    if (name != null) {
      int p = name.indexOf("://");
      if (0 < p) {
        name = name.substring(p + 3);
      }

      p = name.indexOf(".");
      if (0 < p) {
        name = name.substring(p + 1);
        name = "DC=" + name.replaceAll("\\.", ",DC=");
      } else {
        name = null;
      }
    }
    return name;
  }

  public static String domainOf(String name) {
    if (name != null) {
      int p = name.indexOf("://");
      if (0 < p) {
        name = name.substring(p + 3);
      }
      p = name.indexOf(".");
      if (0 < p) {
        name = name.substring(p + 1);
      }
    }
    return name;
  }

  public static void extract(Path dst, Class<?> sibling, String name) throws IOException {
    try (InputStream in = open(sibling, name)) {
      if (in != null) {
        copy(dst, ByteStreams.toByteArray(in));
      }
    }
  }

  private static InputStream open(Class<?> sibling, String name) {
    final InputStream in = sibling.getResourceAsStream(name);
    if (in == null) {
      String pkg = sibling.getName();
      int end = pkg.lastIndexOf('.');
      if (0 < end) {
        pkg = pkg.substring(0, end + 1);
        pkg = pkg.replace('.', '/');
      } else {
        pkg = "";
      }
      System.err.println("warn: Cannot read " + pkg + name);
      return null;
    }
    return in;
  }

  public static void copy(Path dst, byte[] buf) throws FileNotFoundException, IOException {
    // If the file already has the content we want to put there,
    // don't attempt to overwrite the file.
    //
    try (InputStream in = Files.newInputStream(dst)) {
      if (Arrays.equals(buf, ByteStreams.toByteArray(in))) {
        return;
      }
    } catch (NoSuchFileException notFound) {
      // Fall through and write the file.
    }

    Files.createDirectories(dst.getParent());
    LockFile lf = new LockFile(dst.toFile());
    if (!lf.lock()) {
      throw new IOException("Cannot lock " + dst);
    }
    try {
      try (InputStream in = new ByteArrayInputStream(buf);
          OutputStream out = lf.getOutputStream()) {
        ByteStreams.copy(in, out);
      }
      if (!lf.commit()) {
        throw new IOException("Cannot commit " + dst);
      }
    } finally {
      lf.unlock();
    }
  }

  public static URI toURI(String url) throws URISyntaxException {
    final URI u = new URI(url);
    if (isAnyAddress(u)) {
      // If the URL uses * it means all addresses on this system, use the
      // current hostname instead in the returned URI.
      //
      final int s = url.indexOf('*');
      url = url.substring(0, s) + hostname() + url.substring(s + 1);
    }
    return new URI(url);
  }

  public static boolean isAnyAddress(URI u) {
    return u.getHost() == null
        && (u.getAuthority().equals("*") || u.getAuthority().startsWith("*:"));
  }

  public static int portOf(URI uri) {
    int port = uri.getPort();
    if (port < 0) {
      port = "https".equals(uri.getScheme()) ? 443 : 80;
    }
    return port;
  }

  private InitUtil() {}
}
