/*
 * 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.hdds.scm.server;

import java.io.IOException;
import java.lang.reflect.Proxy;
import java.math.BigInteger;
import java.security.cert.CRLException;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.ArrayList;

import java.util.List;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.google.common.base.Preconditions;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType;
import org.apache.hadoop.hdds.protocol.proto.SCMRatisProtocol;
import org.apache.hadoop.hdds.scm.ha.SCMHAInvocationHandler;
import org.apache.hadoop.hdds.scm.ha.SCMRatisServer;
import org.apache.hadoop.hdds.scm.metadata.SCMMetadataStore;
import org.apache.hadoop.hdds.security.exception.SCMSecurityException;
import org.apache.hadoop.hdds.security.x509.certificate.authority.CRLApprover;
import org.apache.hadoop.hdds.security.x509.certificate.authority.CertificateStore;
import org.apache.hadoop.hdds.security.x509.crl.CRLInfo;
import org.apache.hadoop.hdds.utils.db.BatchOperation;
import org.apache.hadoop.hdds.utils.db.Table;
import org.bouncycastle.asn1.x509.CRLReason;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v2CRLBuilder;
import org.bouncycastle.operator.OperatorCreationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.hadoop.ozone.OzoneConsts.CRL_SEQUENCE_ID_KEY;
import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType.SCM;
import static org.apache.hadoop.hdds.security.x509.certificate.authority.CertificateStore.CertType.VALID_CERTS;

/**
 * A Certificate Store class that persists certificates issued by SCM CA.
 */
public final class SCMCertStore implements CertificateStore {
  private static final Logger LOG =
      LoggerFactory.getLogger(SCMCertStore.class);
  private SCMMetadataStore scmMetadataStore;
  private final Lock lock;
  private AtomicLong crlSequenceId;

  private SCMCertStore(SCMMetadataStore dbStore, long sequenceId) {
    this.scmMetadataStore = dbStore;
    lock = new ReentrantLock();
    crlSequenceId = new AtomicLong(sequenceId);
  }

  @Override
  public void storeValidCertificate(BigInteger serialID,
      X509Certificate certificate, NodeType role)
      throws IOException {
    lock.lock();
    try {
      // This makes sure that no certificate IDs are reusable.
      if (role == SCM) {
        // If the role is SCM, store certificate in scm cert table
        // and valid cert table. This is to help to return scm certs during
        // getCertificate call.
        storeValidScmCertificate(serialID, certificate);
      } else {
        // As we don't have different table for other roles, other role
        // certificates will go to validCertsTable.
        scmMetadataStore.getValidCertsTable().put(serialID, certificate);
      }
    } finally {
      lock.unlock();
    }
  }

  /**
   * Writes a new SCM certificate that was issued to the persistent store.
   * @param serialID - Certificate Serial Number.
   * @param certificate - Certificate to persist.
   * @throws IOException - on Failure.
   */
  private void storeValidScmCertificate(BigInteger serialID,
      X509Certificate certificate) throws IOException {
    lock.lock();
    try {
      BatchOperation batchOperation =
          scmMetadataStore.getBatchHandler().initBatchOperation();
      scmMetadataStore.getValidSCMCertsTable().putWithBatch(batchOperation,
          serialID, certificate);
      scmMetadataStore.getValidCertsTable().putWithBatch(batchOperation,
          serialID, certificate);
      scmMetadataStore.getStore().commitBatchOperation(batchOperation);
    } finally {
      lock.unlock();
    }
  }

  public void checkValidCertID(BigInteger serialID) throws IOException {
    lock.lock();
    try {
      if ((getCertificateByID(serialID, VALID_CERTS) != null) ||
          (getCertificateByID(serialID, CertType.REVOKED_CERTS) != null)) {
        throw new SCMSecurityException("Conflicting certificate ID" + serialID);
      }
    } finally {
      lock.unlock();
    }
  }

  @Override
  public Optional<Long> revokeCertificates(
      List<BigInteger> serialIDs,
      X509CertificateHolder caCertificateHolder,
      CRLReason reason,
      Date revocationTime,
      CRLApprover crlApprover)
      throws IOException {
    Date now = new Date();
    X509v2CRLBuilder builder =
        new X509v2CRLBuilder(caCertificateHolder.getIssuer(), now);
    List<X509Certificate> certsToRevoke = new ArrayList<>();
    X509CRL crl;
    Optional<Long> sequenceId = Optional.empty();
    lock.lock();
    try {
      for (BigInteger serialID: serialIDs) {
        X509Certificate cert =
            getCertificateByID(serialID, CertType.VALID_CERTS);
        if (cert == null && LOG.isWarnEnabled()) {
          LOG.warn("Trying to revoke a certificate that is not valid. " +
              "Serial ID: {}", serialID.toString());
        } else if (getCertificateByID(serialID, CertType.REVOKED_CERTS)
            != null) {
          LOG.warn("Trying to revoke a certificate that is already revoked.");
        } else {
          builder.addCRLEntry(serialID, revocationTime,
              reason.getValue().intValue());
          certsToRevoke.add(cert);
        }
      }
      if (!certsToRevoke.isEmpty()) {
        try {
          crl = crlApprover.sign(builder);
        } catch (OperatorCreationException | CRLException e) {
          throw new SCMSecurityException("Unable to create Certificate " +
              "Revocation List.", e);
        }
        // let us do this in a transaction.
        try (BatchOperation batch =
                 scmMetadataStore.getStore().initBatchOperation()) {
          // Move the certificates from Valid Certs table to Revoked Certs Table
          // only if the revocation time has passed.
          if (now.after(revocationTime) || now.equals(revocationTime)) {
            for (X509Certificate cert : certsToRevoke) {
              scmMetadataStore.getRevokedCertsTable()
                  .putWithBatch(batch, cert.getSerialNumber(), cert);
              scmMetadataStore.getValidCertsTable()
                  .deleteWithBatch(batch, cert.getSerialNumber());
            }
          }
          long id = crlSequenceId.incrementAndGet();
          CRLInfo crlInfo = new CRLInfo.Builder()
              .setX509CRL(crl)
              .setCreationTimestamp(now.getTime())
              .build();
          scmMetadataStore.getCRLInfoTable().putWithBatch(
              batch, id, crlInfo);

          // Update the CRL Sequence Id Table with the last sequence id.
          scmMetadataStore.getCRLSequenceIdTable().putWithBatch(batch,
              CRL_SEQUENCE_ID_KEY, id);
          scmMetadataStore.getStore().commitBatchOperation(batch);
          sequenceId = Optional.of(id);
        }
      }
    } finally {
      lock.unlock();
    }
    return sequenceId;
  }

  @Override
  public void removeExpiredCertificate(BigInteger serialID)
      throws IOException {
    // TODO: Later this allows removal of expired certificates from the system.
  }

  @Override
  public X509Certificate getCertificateByID(BigInteger serialID,
                                            CertType certType)
      throws IOException {
    if (certType == VALID_CERTS) {
      return scmMetadataStore.getValidCertsTable().get(serialID);
    } else {
      return scmMetadataStore.getRevokedCertsTable().get(serialID);
    }
  }

  @Override
  public List<X509Certificate> listCertificate(NodeType role,
      BigInteger startSerialID, int count, CertType certType)
      throws IOException {

    Preconditions.checkNotNull(startSerialID);

    if (startSerialID.longValue() == 0) {
      startSerialID = null;
    }

    List<? extends Table.KeyValue<BigInteger, X509Certificate>> certs =
        getCertTableList(role, certType, startSerialID, count);

    List<X509Certificate> results = new ArrayList<>(certs.size());

    for (Table.KeyValue<BigInteger, X509Certificate> kv : certs) {
      try {
        X509Certificate cert = kv.getValue();
        results.add(cert);
      } catch (IOException e) {
        LOG.error("Fail to list certificate from SCM metadata store", e);
        throw new SCMSecurityException(
            "Fail to list certificate from SCM metadata store.");
      }
    }
    return results;
  }

  private List<? extends Table.KeyValue<BigInteger, X509Certificate>>
      getCertTableList(NodeType role, CertType certType,
      BigInteger startSerialID, int count)
      throws IOException {
    // Implemented for role SCM and CertType VALID_CERTS.
    // TODO: Implement for role OM/Datanode and for SCM for CertType
    //  REVOKED_CERTS.

    if (role == SCM) {
      if (certType == VALID_CERTS) {
        return scmMetadataStore.getValidSCMCertsTable().getRangeKVs(
            startSerialID, count);
      } else {
        return scmMetadataStore.getRevokedCertsTable().getRangeKVs(
            startSerialID, count);
      }
    } else {
      if (certType == VALID_CERTS) {
        return scmMetadataStore.getValidCertsTable().getRangeKVs(
            startSerialID, count);
      } else {
        return scmMetadataStore.getRevokedCertsTable().getRangeKVs(
            startSerialID, count);
      }
    }
  }

  /**
   * Reinitialise the underlying store with SCMMetaStore
   * during SCM StateMachine reload.
   * @param metadataStore
   */
  @Override
  public void reinitialize(SCMMetadataStore metadataStore) {
    this.scmMetadataStore = metadataStore;
  }

  public static class Builder {

    private SCMMetadataStore metadataStore;
    private long crlSequenceId;
    private SCMRatisServer scmRatisServer;


    public Builder setMetadaStore(SCMMetadataStore scmMetadataStore) {
      this.metadataStore = scmMetadataStore;
      return this;
    }

    public Builder setCRLSequenceId(long sequenceId) {
      this.crlSequenceId = sequenceId;
      return this;
    }

    public Builder setRatisServer(final SCMRatisServer ratisServer) {
      scmRatisServer = ratisServer;
      return this;
    }

    public CertificateStore build() {
      final SCMCertStore scmCertStore = new SCMCertStore(metadataStore,
          crlSequenceId);

      final SCMHAInvocationHandler scmhaInvocationHandler =
          new SCMHAInvocationHandler(SCMRatisProtocol.RequestType.CERT_STORE,
              scmCertStore, scmRatisServer);

      return (CertificateStore) Proxy.newProxyInstance(
          SCMHAInvocationHandler.class.getClassLoader(),
          new Class<?>[]{CertificateStore.class}, scmhaInvocationHandler);

    }
  }
}
