/*
 * 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.samza.table.remote.couchbase;

import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.CouchbaseCluster;
import com.couchbase.client.java.auth.CertAuthenticator;
import com.couchbase.client.java.env.CouchbaseEnvironment;
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * The CouchbaseBucketRegistry is intended to reuse the same {@link Cluster} instance given same clusterNodes and reuse
 * the same {@link Bucket} given same bucketName. Instantiating a Bucket is expensive. Different tasks within a
 * container that is using the same bucket should use this registry to avoid creating multiple Buckets.
 */
public class CouchbaseBucketRegistry {
  private static final Logger LOGGER = LoggerFactory.getLogger(CouchbaseBucketRegistry.class);
  private final Map<String, Bucket> openedBuckets;
  private final Map<String, Cluster> openedClusters;
  private final Map<String, Integer> bucketUsageCounts;
  private final Map<String, Integer> clusterUsageCounts;

  /**
   * Constructor of the CouchbaseTableRegistry.
   */
  public CouchbaseBucketRegistry() {
    openedBuckets = new HashMap<>();
    openedClusters = new HashMap<>();
    bucketUsageCounts = new HashMap<>();
    clusterUsageCounts = new HashMap<>();
  }

  /**
   * A synchronized method to open a bucket given the bucket name and cluster nodes. Once a bucket has been opened,
   * the reference of the bucket will be stored in the registry, and the same reference will be returned given same
   * bucket name. Each time this method is called, the counter of usage of the bucket is increased by one.
   * @param bucketName name of the bucket to be opened
   * @param clusterNodes list of cluster nodes
   * @param configs couchbase environment configs
   * @return A Bucket instance associated with the bucket name and cluster nodes
   */
  public synchronized Bucket getBucket(String bucketName, List<String> clusterNodes,
      CouchbaseEnvironmentConfigs configs) {
    String bucketId = getBucketId(bucketName, clusterNodes);
    String clusterId = getClusterId(clusterNodes);
    if (!openedClusters.containsKey(clusterId)) {
      openedClusters.put(clusterId, openCluster(clusterNodes, configs));
    }
    if (!openedBuckets.containsKey(bucketId)) {
      openedBuckets.put(bucketId, openBucket(bucketName, openedClusters.get(clusterId)));
    }
    bucketUsageCounts.put(bucketId, bucketUsageCounts.getOrDefault(bucketId, 0) + 1);
    clusterUsageCounts.put(clusterId, clusterUsageCounts.getOrDefault(clusterId, 0) + 1);
    return openedBuckets.get(bucketId);
  }

  /**
   * A synchronized method to close a bucket given the bucket name. Each time this method is called, the counter of
   * usage of the bucket is decreased by one. Only when the counter becomes zero will the bucket be actually closed.
   * Same for cluster, only when all buckets within a cluster have been closed will the cluster be closed.
   * @param bucketName name of the bucket to be opened
   * @param clusterNodes list of cluster nodes
   * @return true if bucket is closed successfully, otherwise false.
   */
  public synchronized boolean closeBucket(String bucketName, List<String> clusterNodes) {
    String bucketId = getBucketId(bucketName, clusterNodes);
    String clusterId = getClusterId(clusterNodes);
    if (!openedBuckets.containsKey(bucketId) || !openedClusters.containsKey(clusterId)) {
      return false;
    }
    bucketUsageCounts.put(bucketId, bucketUsageCounts.get(bucketId) - 1);
    clusterUsageCounts.put(clusterId, clusterUsageCounts.get(clusterId) - 1);
    Boolean bucketClosed = true;
    Boolean clusterClosed = true;
    if (bucketUsageCounts.get(bucketId) == 0) {
      bucketClosed = openedBuckets.get(bucketId).close();
      openedBuckets.remove(bucketId);
      bucketUsageCounts.remove(bucketId);
      if (clusterUsageCounts.get(clusterId) == 0) {
        clusterClosed = openedClusters.get(clusterId).disconnect();
        openedClusters.remove(clusterId);
        clusterUsageCounts.remove(clusterId);
      }
    }
    return bucketClosed && clusterClosed;
  }

  /**
   * Helper method to open a cluster given cluster nodes and environment configurations.
   */
  private Cluster openCluster(List<String> clusterNodes, CouchbaseEnvironmentConfigs configs) {
    DefaultCouchbaseEnvironment.Builder envBuilder = new DefaultCouchbaseEnvironment.Builder();
    if (configs.sslEnabled != null) {
      envBuilder.sslEnabled(configs.sslEnabled);
    }
    if (configs.certAuthEnabled != null) {
      envBuilder.certAuthEnabled(configs.certAuthEnabled);
    }
    if (configs.sslKeystoreFile != null) {
      envBuilder.sslKeystoreFile(configs.sslKeystoreFile);
    }
    if (configs.sslKeystorePassword != null) {
      envBuilder.sslKeystorePassword(configs.sslKeystorePassword);
    }
    if (configs.sslTruststoreFile != null) {
      envBuilder.sslTruststoreFile(configs.sslTruststoreFile);
    }
    if (configs.sslTruststorePassword != null) {
      envBuilder.sslTruststorePassword(configs.sslTruststorePassword);
    }
    if (configs.bootstrapCarrierDirectPort != null) {
      envBuilder.bootstrapCarrierDirectPort(configs.bootstrapCarrierDirectPort);
    }
    if (configs.bootstrapCarrierSslPort != null) {
      envBuilder.bootstrapCarrierSslPort(configs.bootstrapCarrierSslPort);
    }
    if (configs.bootstrapHttpDirectPort != null) {
      envBuilder.bootstrapHttpDirectPort(configs.bootstrapHttpDirectPort);
    }
    if (configs.bootstrapHttpSslPort != null) {
      envBuilder.bootstrapHttpSslPort(configs.bootstrapHttpSslPort);
    }
    CouchbaseEnvironment env = envBuilder.build();
    Cluster cluster = CouchbaseCluster.create(env, clusterNodes);
    if (configs.sslEnabled != null && configs.sslEnabled) {
      cluster.authenticate(CertAuthenticator.INSTANCE);
    } else if (configs.username != null) {
      cluster.authenticate(configs.username, configs.password);
    } else {
      LOGGER.warn("No authentication is enabled for cluster: {}. This is not recommended except for test cases.",
          clusterNodes);
    }
    return cluster;
  }

  /**
   * Helper method to open a bucket with given bucket name and cluster
   */
  private Bucket openBucket(String bucketName, Cluster cluster) {
    return cluster.openBucket(bucketName);
  }

  /**
   * Generate a unique bucketId given bucket name and cluster nodes.
   */
  private String getBucketId(String bucketName, List<String> clusterNodes) {
    return getClusterId(clusterNodes) + "-" + bucketName;
  }

  /**
   * Generate a unique clusterId given cluster nodes.
   */
  private String getClusterId(List<String> clusterNodes) {
    return clusterNodes.toString();
  }
}
