/*
 * 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.system.azureblob.avro;

import com.azure.storage.blob.BlobContainerAsyncClient;
import com.azure.storage.blob.specialized.BlockBlobAsyncClient;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import org.apache.samza.system.azureblob.compression.Compression;
import org.apache.samza.system.azureblob.producer.AzureBlobWriter;
import org.apache.samza.system.azureblob.producer.AzureBlobWriterMetrics;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.Executor;
import org.apache.avro.Schema;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.IndexedRecord;
import org.apache.avro.io.BinaryEncoder;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.specific.SpecificDatumWriter;
import org.apache.avro.specific.SpecificRecord;
import org.apache.samza.SamzaException;
import org.apache.samza.config.Config;
import org.apache.samza.system.OutgoingMessageEnvelope;
import org.apache.samza.system.azureblob.utils.BlobMetadataGeneratorFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class implements {@link org.apache.samza.system.azureblob.producer.AzureBlobWriter}
 * for writing avro records to Azure Blob Storage.
 *
 * It uses {@link org.apache.avro.file.DataFileWriter} to convert avro records it receives to byte[].
 * This byte[] is passed on to {@link org.apache.samza.system.azureblob.avro.AzureBlobOutputStream}.
 * AzureBlobOutputStream in turn uploads data to Storage as a blob.
 *
 * It also accepts encoded records as byte[] as long as the first OutgoingMessageEnvelope this writer receives
 * is a decoded record from which to get the schema and record type (GenericRecord vs SpecificRecord).
 * The subsequent encoded records are written directly to AzureBlobOutputStream without checking if they conform
 * to the schema. It is the responsibility of the user to ensure this. Failing to do so may result in an
 * unreadable avro blob.
 *
 * It expects all OutgoingMessageEnvelopes to be of the same schema.
 * To handle schema evolution (sending envelopes of different schema), this writer has to be closed and a new writer
 * has to be created. The first envelope of the new writer should contain a valid record to get schema from.
 * If used by AzureBlobSystemProducer, this is done through systemProducer.flush(source).
 *
 * Once closed this object can not be used.
 * This is a thread safe class.
 *
 * If the number of records or size of the current blob exceeds the specified limits then a new blob is created.
 */
public class AzureBlobAvroWriter implements AzureBlobWriter {
  private static final Logger LOG = LoggerFactory.getLogger(AzureBlobAvroWriter.class);
  private static final String PUBLISHED_FILE_NAME_DATE_FORMAT = "yyyy/MM/dd/HH/mm-ss";
  private static final String BLOB_NAME_AVRO = "%s/%s.avro%s";
  private static final String BLOB_NAME_RANDOM_STRING_AVRO = "%s/%s-%s.avro%s";
  private static final SimpleDateFormat UTC_FORMATTER = buildUTCFormatter();

  // Avro's DataFileWriter has internal buffers and also adds metadata.
  // Based on the current default sizes of these buffers and metadata, the data overhead is a little less than 100KB
  // However, taking the overhead to be capped at 1MB to ensure enough room if the default values are increased.
  static final long DATAFILEWRITER_OVERHEAD = 1000000; // 1MB

  // currentBlobWriterComponents == null only for the first blob immediately after this AzureBlobAvroWriter object has been created.
  // rest of this object's lifecycle, currentBlobWriterComponents is not null.
  private BlobWriterComponents currentBlobWriterComponents = null;
  private final List<BlobWriterComponents> allBlobWriterComponents = new ArrayList<>();
  private Schema schema = null;
  // datumWriter == null only for the first blob immediately after this AzureBlobAvroWriter object has been created.
  // It is created from the schema taken from the first OutgoingMessageEnvelope. Hence the first OME has to be a decoded avro record.
  // For rest of this object's lifecycle, datumWriter is not null.
  private DatumWriter<IndexedRecord> datumWriter = null;
  private volatile boolean isClosed = false;

  private final Executor blobThreadPool;
  private final AzureBlobWriterMetrics metrics;
  private final int maxBlockFlushThresholdSize;
  private final long flushTimeoutMs;
  private final Compression compression;
  private final BlobContainerAsyncClient containerAsyncClient;
  private final String blobURLPrefix;
  private final long maxBlobSize;
  private final long maxRecordsPerBlob;
  private final boolean useRandomStringInBlobName;
  private final Object currentDataFileWriterLock = new Object();
  private volatile long recordsInCurrentBlob = 0;
  private BlobMetadataGeneratorFactory blobMetadataGeneratorFactory;
  private Config blobMetadataGeneratorConfig;
  private String streamName;

  public AzureBlobAvroWriter(BlobContainerAsyncClient containerAsyncClient, String blobURLPrefix,
      Executor blobThreadPool, AzureBlobWriterMetrics metrics,
      BlobMetadataGeneratorFactory blobMetadataGeneratorFactory, Config blobMetadataGeneratorConfig, String streamName,
      int maxBlockFlushThresholdSize, long flushTimeoutMs, Compression compression, boolean useRandomStringInBlobName,
      long maxBlobSize, long maxRecordsPerBlob) {

    this.blobThreadPool = blobThreadPool;
    this.metrics = metrics;
    this.maxBlockFlushThresholdSize = maxBlockFlushThresholdSize;
    this.flushTimeoutMs = flushTimeoutMs;
    this.compression = compression;
    this.containerAsyncClient = containerAsyncClient;
    this.blobURLPrefix = blobURLPrefix;
    this.useRandomStringInBlobName = useRandomStringInBlobName;
    this.maxBlobSize = maxBlobSize;
    this.maxRecordsPerBlob = maxRecordsPerBlob;
    this.blobMetadataGeneratorFactory = blobMetadataGeneratorFactory;
    this.blobMetadataGeneratorConfig = blobMetadataGeneratorConfig;
    this.streamName = streamName;
  }

  /**
   * This method expects the {@link org.apache.samza.system.OutgoingMessageEnvelope}
   * to contain a message which is a {@link org.apache.avro.generic.IndexedRecord} or an encoded record aka byte[].
   * If the record is already encoded, it will directly write the byte[] to the output stream without checking if it conforms to schema.
   * Else, it encodes the record and writes to output stream.
   * However, the first envelope should always be a record and not a byte[].
   * If the blocksize threshold crosses, it will upload the output stream contents as a block.
   * If the number of records in current blob or size of current blob exceed limits then a new blob is created.
   * Multi-threading and thread-safety:
   *  The underlying {@link org.apache.avro.file.DataFileWriter} is not thread-safe.
   *  For this reason, it is essential to wrap accesses to this object in a synchronized block.
   *  Method write(OutgoingMessageEnvelope) allows multiple threads to encode records as that operation is stateless but
   *  restricts access to the shared objects through the synchronized block.
   *  Concurrent access to shared objects is controlled through a common lock and synchronized block and hence ensures
   *  thread safety.
   * @param ome - OutgoingMessageEnvelope that contains the IndexedRecord (GenericRecord or SpecificRecord) or an encoded record as byte[]
   * @throws IOException when
   *       - OutgoingMessageEnvelope's message is not an IndexedRecord or
   *       - underlying dataFileWriter.append fails
   * @throws IllegalStateException when the first OutgoingMessageEnvelope's message is not a record.
   */
  @Override
  public void write(OutgoingMessageEnvelope ome) throws IOException {
    Optional<IndexedRecord> optionalIndexedRecord;
    byte[] encodedRecord;
    if (ome.getMessage() instanceof IndexedRecord) {
      optionalIndexedRecord = Optional.of((IndexedRecord) ome.getMessage());
      encodedRecord = encodeRecord((IndexedRecord) ome.getMessage());
    } else if (ome.getMessage() instanceof byte[]) {
      optionalIndexedRecord = Optional.empty();
      encodedRecord = (byte[]) ome.getMessage();
    } else {
      throw new IllegalArgumentException("AzureBlobAvroWriter only supports IndexedRecord and byte[].");
    }

    synchronized (currentDataFileWriterLock) {
      // if currentBlobWriterComponents is null, then it is the first blob of this AzureBlobAvroWriter object
      if (currentBlobWriterComponents == null || willCurrentBlobExceedSize(encodedRecord) || willCurrentBlobExceedRecordLimit()) {
        startNextBlob(optionalIndexedRecord);
      }
      currentBlobWriterComponents.dataFileWriter.appendEncoded(ByteBuffer.wrap(encodedRecord));
      recordsInCurrentBlob++;
      // incrementNumberOfRecordsInBlob should always be invoked every time appendEncoded above is invoked.
      // this is to count the number records in a blob and then use that count as a metadata of the blob.
      currentBlobWriterComponents.azureBlobOutputStream.incrementNumberOfRecordsInBlob();
    }
  }
  /**
   * This method flushes all records written in dataFileWriter to the underlying AzureBlobOutputStream.
   * dataFileWriter.flush then explicitly invokes flush of the AzureBlobOutputStream.
   * This in turn async uploads content of the output stream as a block and reinits the output stream.
   * AzureBlobOutputStream.flush is not ensured if dataFileWriter.flush fails.
   * In such a scenario, the current block is not uploaded and blocks uploaded so far are lost.
   * {@inheritDoc}
   * @throws IOException if underlying dataFileWriter.flush fails
   */
  @Override
  public void flush() throws IOException {
    synchronized (currentDataFileWriterLock) {
      currentBlobWriterComponents.dataFileWriter.flush();
    }
  }

  /**
   * This method closes all DataFileWriters and output streams associated with all the blobs created.
   * flush should be explicitly called before close.
   * {@inheritDoc}
   * @throws IllegalStateException when closing a closed writer
   * @throws SamzaException if underlying DataFileWriter.close fails
   */
  @Override
  public void close() {
    synchronized (currentDataFileWriterLock) {
      if (isClosed) {
        throw new IllegalStateException("Attempting to close an already closed AzureBlobAvroWriter");
      }
      allBlobWriterComponents.forEach(blobWriterComponents -> {
        try {
          closeDataFileWriter(blobWriterComponents.dataFileWriter, blobWriterComponents.azureBlobOutputStream,
              blobWriterComponents.blockBlobAsyncClient);
        } catch (IOException e) {
          throw new SamzaException(e);
        }
      });
      isClosed = true;
    }
  }

  @VisibleForTesting
  AzureBlobAvroWriter(BlobContainerAsyncClient containerAsyncClient, AzureBlobWriterMetrics metrics,
      Executor blobThreadPool, int maxBlockFlushThresholdSize, int flushTimeoutMs, String blobURLPrefix,
      DataFileWriter<IndexedRecord> dataFileWriter,
      AzureBlobOutputStream azureBlobOutputStream, BlockBlobAsyncClient blockBlobAsyncClient,
      BlobMetadataGeneratorFactory blobMetadataGeneratorFactory, Config blobMetadataGeneratorConfig, String streamName,
      long maxBlobSize, long maxRecordsPerBlob, Compression compression, boolean useRandomStringInBlobName) {
    if (dataFileWriter == null || azureBlobOutputStream == null || blockBlobAsyncClient == null) {
      this.currentBlobWriterComponents = null;
    } else {
      this.currentBlobWriterComponents =
          new BlobWriterComponents(dataFileWriter, azureBlobOutputStream, blockBlobAsyncClient);
    }
    this.allBlobWriterComponents.add(this.currentBlobWriterComponents);
    this.blobThreadPool = blobThreadPool;
    this.blobURLPrefix = blobURLPrefix;
    this.metrics = metrics;
    this.maxBlockFlushThresholdSize = maxBlockFlushThresholdSize;
    this.flushTimeoutMs = flushTimeoutMs;
    this.compression = compression;
    this.containerAsyncClient = containerAsyncClient;
    this.useRandomStringInBlobName = useRandomStringInBlobName;
    this.maxBlobSize = maxBlobSize;
    this.maxRecordsPerBlob = maxRecordsPerBlob;
    this.blobMetadataGeneratorFactory = blobMetadataGeneratorFactory;
    this.blobMetadataGeneratorConfig = blobMetadataGeneratorConfig;
    this.streamName = streamName;
  }

  @VisibleForTesting
  byte[] encodeRecord(IndexedRecord record) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    Schema schema = record.getSchema();
    try {
      EncoderFactory encoderfactory = new EncoderFactory();
      BinaryEncoder encoder = encoderfactory.binaryEncoder(out, null);
      DatumWriter<IndexedRecord> writer;
      if (record instanceof SpecificRecord) {
        writer = new SpecificDatumWriter<>(schema);
      } else {
        writer = new GenericDatumWriter<>(schema);
      }
      writer.write(record, encoder);
      encoder.flush(); //encoder may buffer
    } catch (Exception e) {
      throw new SamzaException("Unable to serialize Avro record using schema within the record: " + schema.toString(), e);
    }
    return out.toByteArray();
  }

  private static SimpleDateFormat buildUTCFormatter() {
    SimpleDateFormat formatter = new SimpleDateFormat(PUBLISHED_FILE_NAME_DATE_FORMAT);
    formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
    return formatter;
  }

  private void closeDataFileWriter(DataFileWriter dataFileWriter, AzureBlobOutputStream azureBlobOutputStream,
      BlockBlobAsyncClient blockBlobAsyncClient) throws IOException {
    try {
      LOG.info("Closing the blob: {}", blockBlobAsyncClient.getBlobUrl().toString());
      // dataFileWriter.close calls close of the azureBlobOutputStream associated with it.
      dataFileWriter.close();
    } catch (Exception e) {
      LOG.error("Exception occurred during DataFileWriter.close for blob  "
          + blockBlobAsyncClient.getBlobUrl()
          + ". All blocks uploaded so far for this blob will be discarded to avoid invalid blobs.");
      throw e;
    }
  }

  private void startNextBlob(Optional<IndexedRecord> optionalIndexedRecord) throws IOException {
    if (currentBlobWriterComponents != null) {
      LOG.info("Starting new blob as current blob size is "
          + currentBlobWriterComponents.azureBlobOutputStream.getSize()
          + " and max blob size is " + maxBlobSize
          + " or number of records is " + recordsInCurrentBlob
          + " and max records in blob is " + maxRecordsPerBlob);
      currentBlobWriterComponents.dataFileWriter.flush();
      currentBlobWriterComponents.azureBlobOutputStream.releaseBuffer();
      recordsInCurrentBlob = 0;
    }
    // datumWriter is null when AzureBlobAvroWriter is created but has not yet received a message.
    // optionalIndexedRecord is the first message in this case.
    if (datumWriter == null) {
      if (optionalIndexedRecord.isPresent()) {
        IndexedRecord record = optionalIndexedRecord.get();
        schema = record.getSchema();
        if (record instanceof SpecificRecord) {
          datumWriter = new SpecificDatumWriter<>(schema);
        } else {
          datumWriter = new GenericDatumWriter<>(schema);
        }
      } else {
        throw new IllegalStateException("Writing without schema setup.");
      }
    }
    String blobURL;
    if (useRandomStringInBlobName) {
      blobURL = String.format(BLOB_NAME_RANDOM_STRING_AVRO, blobURLPrefix,
          UTC_FORMATTER.format(System.currentTimeMillis()), UUID.randomUUID().toString().substring(0, 8),
          compression.getFileExtension());
    } else {
      blobURL = String.format(BLOB_NAME_AVRO, blobURLPrefix,
          UTC_FORMATTER.format(System.currentTimeMillis()), compression.getFileExtension());
    }
    LOG.info("Creating new blob: {}", blobURL);
    BlockBlobAsyncClient blockBlobAsyncClient = containerAsyncClient.getBlobAsyncClient(blobURL).getBlockBlobAsyncClient();

    DataFileWriter<IndexedRecord> dataFileWriter = new DataFileWriter<>(datumWriter);
    AzureBlobOutputStream azureBlobOutputStream;
    try {
      azureBlobOutputStream = new AzureBlobOutputStream(blockBlobAsyncClient, blobThreadPool, metrics,
          blobMetadataGeneratorFactory, blobMetadataGeneratorConfig,
          streamName, flushTimeoutMs, maxBlockFlushThresholdSize, compression);
    } catch (Exception e) {
      throw new SamzaException("Unable to create AzureBlobOutputStream", e);
    }
    dataFileWriter.create(schema, azureBlobOutputStream);
    dataFileWriter.setFlushOnEveryBlock(false);
    this.currentBlobWriterComponents = new BlobWriterComponents(dataFileWriter, azureBlobOutputStream, blockBlobAsyncClient);
    allBlobWriterComponents.add(this.currentBlobWriterComponents);
    LOG.info("Created new blob: {}", blobURL);
  }

  private boolean willCurrentBlobExceedSize(byte[] encodedRecord) {
    AzureBlobOutputStream azureBlobOutputStream = currentBlobWriterComponents.azureBlobOutputStream;
    return (azureBlobOutputStream.getSize() + encodedRecord.length + DATAFILEWRITER_OVERHEAD) > maxBlobSize;
  }

  private boolean willCurrentBlobExceedRecordLimit() {
    return (recordsInCurrentBlob + 1) > maxRecordsPerBlob;
  }

  /**
   * Holds the components needed to write to an Azure Blob
   * - including Avro's DataFileWriter, AzureBlobOutputStream and Azure's BlockBlobAsyncClient
   */
  private class BlobWriterComponents {
    final DataFileWriter<IndexedRecord> dataFileWriter;
    final AzureBlobOutputStream azureBlobOutputStream;
    final BlockBlobAsyncClient blockBlobAsyncClient;

    public BlobWriterComponents(DataFileWriter dataFileWriter, AzureBlobOutputStream azureBlobOutputStream,
        BlockBlobAsyncClient blockBlobAsyncClient) {
      Preconditions.checkNotNull(dataFileWriter, "DataFileWriter can not be null when creating WriterComponents for an Azure Blob.");
      Preconditions.checkNotNull(azureBlobOutputStream, "AzureBlobOutputStream can not be null when creating WriterComponents for an Azure Blob.");
      Preconditions.checkNotNull(blockBlobAsyncClient, "BlockBlobAsyncClient can not be null when creating WriterComponents for an Azure Blob.");
      this.dataFileWriter = dataFileWriter;
      this.azureBlobOutputStream = azureBlobOutputStream;
      this.blockBlobAsyncClient = blockBlobAsyncClient;
    }
  }
}
