/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.hadoop.registry.server.dns;

import com.google.common.annotations.VisibleForTesting;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.util.SubnetUtils;
import org.apache.hadoop.conf.Configuration;
import static org.apache.hadoop.registry.client.api.RegistryConstants.KEY_DNS_SPLIT_REVERSE_ZONE_RANGE;
import static org.apache.hadoop.registry.client.api.RegistryConstants.KEY_DNS_ZONE_MASK;
import static org.apache.hadoop.registry.client.api.RegistryConstants.KEY_DNS_ZONE_SUBNET;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Utilities for configuring reverse zones.
 */
public final class ReverseZoneUtils {

  private static final Logger LOG =
      LoggerFactory.getLogger(ReverseZoneUtils.class);

  private static final long POW3 = (long) Math.pow(256, 3);
  private static final long POW2 = (long) Math.pow(256, 2);
  private static final long POW1 = (long) Math.pow(256, 1);

  private ReverseZoneUtils() {
  }

  /**
   * Given a baseIp, range and index, return the network address for the
   * reverse zone.
   *
   * @param baseIp base ip address to perform calculations against.
   * @param range  number of ip addresses per subnet.
   * @param index  the index of the subnet to calculate.
   * @return the calculated ip address.
   * @throws UnknownHostException if an invalid ip is provided.
   */
  protected static String getReverseZoneNetworkAddress(String baseIp, int range,
      int index) throws UnknownHostException {
    if (index < 0) {
      throw new IllegalArgumentException(
          String.format("Invalid index provided, must be positive: %d", index));
    }
    if (range < 0) {
      throw new IllegalArgumentException(
          String.format("Invalid range provided, cannot be negative: %d",
              range));
    }
    return calculateIp(baseIp, range, index);
  }

  /**
   * When splitting the reverse zone, return the number of subnets needed,
   * given the range and netmask.
   *
   * @param conf the Hadoop configuration.
   * @return The number of subnets given the range and netmask.
   */
  protected static int getSubnetCountForReverseZones(Configuration conf) {
    String subnet = conf.get(KEY_DNS_ZONE_SUBNET);
    String mask = conf.get(KEY_DNS_ZONE_MASK);
    String range = conf.get(KEY_DNS_SPLIT_REVERSE_ZONE_RANGE);

    int parsedRange;
    try {
      parsedRange = Integer.parseInt(range);
    } catch (NumberFormatException e) {
      LOG.error("The supplied range is not a valid integer: Supplied range: ",
          range);
      throw e;
    }
    if (parsedRange < 0) {
      String msg = String
          .format("Range cannot be negative: Supplied range: %d", parsedRange);
      LOG.error(msg);
      throw new IllegalArgumentException(msg);
    }

    int ipCount;
    try {
      SubnetUtils subnetUtils = new SubnetUtils(subnet, mask);
      subnetUtils.setInclusiveHostCount(true);
      ipCount = subnetUtils.getInfo().getAddressCount();

    } catch (IllegalArgumentException e) {
      LOG.error("The subnet or mask is invalid: Subnet: {} Mask: {}", subnet,
          mask);
      throw e;
    }

    if (parsedRange == 0) {
      return ipCount;
    }
    return ipCount / parsedRange;
  }

  private static String calculateIp(String baseIp, int range, int index)
      throws UnknownHostException {
    long[] ipParts = splitIp(baseIp);

    long ipNum1 = POW3 * ipParts[0];
    long ipNum2 = POW2 * ipParts[1];
    long ipNum3 = POW1 * ipParts[2];
    long ipNum4 = ipParts[3];
    long ipNum = ipNum1 + ipNum2 + ipNum3 + ipNum4;

    ArrayList<Long> ipPartsOut = new ArrayList<>();
    // First octet
    long temp = ipNum + range * (long) index;
    ipPartsOut.add(0, temp / POW3);

    // Second octet
    temp = temp - ipPartsOut.get(0) * POW3;
    ipPartsOut.add(1, temp / POW2);

    // Third octet
    temp = temp - ipPartsOut.get(1) * POW2;
    ipPartsOut.add(2, temp / POW1);

    // Fourth octet
    temp = temp - ipPartsOut.get(2) * POW1;
    ipPartsOut.add(3, temp);

    return StringUtils.join(ipPartsOut, '.');
  }

  @VisibleForTesting
  protected static long[] splitIp(String baseIp) throws UnknownHostException {
    InetAddress inetAddress;
    try {
      inetAddress = InetAddress.getByName(baseIp);
    } catch (UnknownHostException e) {
      LOG.error("Base IP address is invalid");
      throw e;
    }
    if (inetAddress instanceof Inet6Address) {
      throw new IllegalArgumentException(
          "IPv6 is not yet supported for " + "reverse zones");
    }
    byte[] octets = inetAddress.getAddress();
    if (octets.length != 4) {
      throw new IllegalArgumentException("Base IP address is invalid");
    }
    long[] results = new long[4];
    for (int i = 0; i < octets.length; i++) {
      results[i] = octets[i] & 0xff;
    }
    return results;
  }

}
