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

import java.io.IOException;
import java.io.InputStream;

import org.apache.avro.Schema;

/**
 * A factory for creating and configuring {@link Decoder}s.
 * <p/>
 * Factories are thread-safe, and are generally cached by applications for
 * performance reasons. Multiple instances are only required if multiple
 * concurrent configurations are needed.
 *
 * @see Decoder
 */

public class DecoderFactory {
  private static final DecoderFactory DEFAULT_FACTORY = new DefaultDecoderFactory();
  static final int DEFAULT_BUFFER_SIZE = 8192;

  int binaryDecoderBufferSize = DEFAULT_BUFFER_SIZE;

  /** Constructor for factory instances */
  public DecoderFactory() {
    super();
  }

  /**
   * @deprecated use the equivalent {@link #get()} instead
   */
  @Deprecated
  public static DecoderFactory defaultFactory() {
    return get();
  }

  /**
   * Returns an immutable static DecoderFactory configured with default settings
   * All mutating methods throw IllegalArgumentExceptions. All creator methods
   * create objects with default settings.
   */
  public static DecoderFactory get() {
    return DEFAULT_FACTORY;
  }

  /**
   * Configures this factory to use the specified buffer size when creating
   * Decoder instances that buffer their input. The default buffer size is
   * 8192 bytes.
   *
   * @param size The preferred buffer size. Valid values are in the range [32,
   *          16*1024*1024]. Values outside this range are rounded to the nearest
   *          value in the range. Values less than 512 or greater than 1024*1024
   *          are not recommended.
   * @return This factory, to enable method chaining:
   * <pre>
   * DecoderFactory myFactory = new DecoderFactory().useBinaryDecoderBufferSize(4096);
   * </pre>
   */
  public DecoderFactory configureDecoderBufferSize(int size) {
    if (size < 32)
      size = 32;
    if (size > 16 * 1024 * 1024)
      size = 16 * 1024 * 1024;
    this.binaryDecoderBufferSize = size;
    return this;
  }

  /**
   * Returns this factory's configured preferred buffer size.  Used when creating
   * Decoder instances that buffer. See {@link #configureDecoderBufferSize}
   * @return The preferred buffer size, in bytes.
   */
  public int getConfiguredBufferSize() {
    return this.binaryDecoderBufferSize;
  }

  /** @deprecated use the equivalent
   *  {@link #binaryDecoder(InputStream, BinaryDecoder)} instead */
  @Deprecated
  public BinaryDecoder createBinaryDecoder(InputStream in, BinaryDecoder reuse) {
    return binaryDecoder(in, reuse);
  }

  /**
   * Creates or reinitializes a {@link BinaryDecoder} with the input stream
   * provided as the source of data. If <i>reuse</i> is provided, it will be
   * reinitialized to the given input stream.
   * <p/>
   * {@link BinaryDecoder} instances returned by this method buffer their input,
   * reading up to {@link #getConfiguredBufferSize()} bytes past the minimum
   * required to satisfy read requests in order to achieve better performance.
   * If the buffering is not desired, use
   * {@link #directBinaryDecoder(InputStream, BinaryDecoder)}.
   * <p/>
   * {@link BinaryDecoder#inputStream()} provides a view on the data that is
   * buffer-aware, for users that need to interleave access to data
   * with the Decoder API.
   *
   * @param in
   *          The InputStream to initialize to
   * @param reuse
   *          The BinaryDecoder to <i>attempt</i> to reuse given the factory
   *          configuration. A BinaryDecoder implementation may not be
   *          compatible with reuse, causing a new instance to be returned. If
   *          null, a new instance is returned.
   * @return A BinaryDecoder that uses <i>in</i> as its source of data. If
   *         <i>reuse</i> is null, this will be a new instance. If <i>reuse</i>
   *         is not null, then it may be reinitialized if compatible, otherwise
   *         a new instance will be returned.
   * @see BinaryDecoder
   * @see Decoder
   */
  public BinaryDecoder binaryDecoder(InputStream in, BinaryDecoder reuse) {
    if (null == reuse || !reuse.getClass().equals(BinaryDecoder.class)) {
      return new BinaryDecoder(in, binaryDecoderBufferSize);
    } else {
      return ((BinaryDecoder)reuse).configure(in, binaryDecoderBufferSize);
    }
  }

  /**
   * Creates or reinitializes a {@link BinaryDecoder} with the input stream
   * provided as the source of data. If <i>reuse</i> is provided, it will be
   * reinitialized to the given input stream.
   * <p/>
   * {@link BinaryDecoder} instances returned by this method do not buffer their input.
   * In most cases a buffering BinaryDecoder is sufficient in combination with
   * {@link BinaryDecoder#inputStream()} which provides a buffer-aware view on
   * the data.
   * <p/>
   * A "direct" BinaryDecoder does not read ahead from an InputStream or other data source
   * that cannot be rewound.  From the perspective of a client, a "direct" decoder
   * must never read beyond the minimum necessary bytes to service a {@link BinaryDecoder}
   * API read request.
   * <p/>
   * In the case that the improved performance of a buffering implementation does not outweigh the
   * inconvenience of its buffering semantics, a "direct" decoder can be
   * used.
   * @param in
   *          The InputStream to initialize to
   * @param reuse
   *          The BinaryDecoder to <i>attempt</i> to reuse given the factory
   *          configuration. A BinaryDecoder implementation may not be
   *          compatible with reuse, causing a new instance to be returned. If
   *          null, a new instance is returned.
   * @return A BinaryDecoder that uses <i>in</i> as its source of data. If
   *         <i>reuse</i> is null, this will be a new instance. If <i>reuse</i>
   *         is not null, then it may be reinitialized if compatible, otherwise
   *         a new instance will be returned.
   * @see DirectBinaryDecoder
   * @see Decoder
   */
  public BinaryDecoder directBinaryDecoder(InputStream in, BinaryDecoder reuse) {
    if (null == reuse || !reuse.getClass().equals(DirectBinaryDecoder.class)) {
      return new DirectBinaryDecoder(in);
    } else {
      return ((DirectBinaryDecoder)reuse).configure(in);
    }
  }

  /** @deprecated use {@link #binaryDecoder(byte[], int, int, BinaryDecoder)}
   * instead */
  @Deprecated
  public BinaryDecoder createBinaryDecoder(byte[] bytes, int offset,
      int length, BinaryDecoder reuse) {
    if (null == reuse || !reuse.getClass().equals(BinaryDecoder.class)) {
      return new BinaryDecoder(bytes, offset, length);
    } else {
      return reuse.configure(bytes, offset, length);
    }
  }

  /**
   * Creates or reinitializes a {@link BinaryDecoder} with the byte array
   * provided as the source of data. If <i>reuse</i> is provided, it will
   * attempt to reinitialize <i>reuse</i> to the new byte array. This instance
   * will use the provided byte array as its buffer.
   * <p/>
   * {@link BinaryDecoder#inputStream()} provides a view on the data that is
   * buffer-aware and can provide a view of the data not yet read by Decoder API
   * methods.
   *
   * @param bytes The byte array to initialize to
   * @param offset The offset to start reading from
   * @param length The maximum number of bytes to read from the byte array
   * @param reuse The BinaryDecoder to attempt to reinitialize. if null a new
   *          BinaryDecoder is created.
   * @return A BinaryDecoder that uses <i>bytes</i> as its source of data. If
   *         <i>reuse</i> is null, this will be a new instance. <i>reuse</i> may
   *         be reinitialized if appropriate, otherwise a new instance is
   *         returned. Clients must not assume that <i>reuse</i> is
   *         reinitialized and returned.
   */
  public BinaryDecoder binaryDecoder(byte[] bytes, int offset,
      int length, BinaryDecoder reuse) {
    if (null == reuse || !reuse.getClass().equals(BinaryDecoder.class)) {
      return new BinaryDecoder(bytes, offset, length);
    } else {
      return reuse.configure(bytes, offset, length);
    }
  }

  /** @deprecated use {@link #binaryDecoder(byte[], BinaryDecoder)} instead */
  @Deprecated
  public BinaryDecoder createBinaryDecoder(byte[] bytes, BinaryDecoder reuse) {
    return binaryDecoder(bytes, 0, bytes.length, reuse);
  }

  /**
   * This method is shorthand for
   * <pre>
   * createBinaryDecoder(bytes, 0, bytes.length, reuse);
   * </pre> {@link #binaryDecoder(byte[], int, int, BinaryDecoder)}
   */
  public BinaryDecoder binaryDecoder(byte[] bytes, BinaryDecoder reuse) {
    return binaryDecoder(bytes, 0, bytes.length, reuse);
  }

  /**
   * Creates a {@link JsonDecoder} using the InputStrim provided for reading
   * data that conforms to the Schema provided.
   * <p/>
   *
   * @param schema
   *          The Schema for data read from this JsonEncoder. Cannot be null.
   * @param input
   *          The InputStream to read from. Cannot be null.
   * @return A JsonEncoder configured with <i>input</i> and <i>schema</i>
   * @throws IOException
   */
  public JsonDecoder jsonDecoder(Schema schema, InputStream input)
      throws IOException {
    return new JsonDecoder(schema, input);
  }

  /**
   * Creates a {@link JsonDecoder} using the String provided for reading data
   * that conforms to the Schema provided.
   * <p/>
   *
   * @param schema
   *          The Schema for data read from this JsonEncoder. Cannot be null.
   * @param input
   *          The String to read from. Cannot be null.
   * @return A JsonEncoder configured with <i>input</i> and <i>schema</i>
   * @throws IOException
   */
  public JsonDecoder jsonDecoder(Schema schema, String input)
      throws IOException {
    return new JsonDecoder(schema, input);
  }

  /**
   * Creates a {@link ValidatingDecoder} wrapping the Decoder provided. This
   * ValidatingDecoder will ensure that operations against it conform to the
   * schema provided.
   *
   * @param schema
   *          The Schema to validate against. Cannot be null.
   * @param wrapped
   *          The Decoder to wrap.
   * @return A ValidatingDecoder configured with <i>wrapped</i> and
   *         <i>schema</i>
   * @throws IOException
   */
  public ValidatingDecoder validatingDecoder(Schema schema, Decoder wrapped)
      throws IOException {
    return new ValidatingDecoder(schema, wrapped);
  }

  /**
   * Creates a {@link ResolvingDecoder} wrapping the Decoder provided. This
   * ResolvingDecoder will resolve input conforming to the <i>writer</i> schema
   * from the wrapped Decoder, and present it as the <i>reader</i> schema.
   *
   * @param writer
   *          The Schema that the source data is in. Cannot be null.
   * @param reader
   *          The Schema that the reader wishes to read the data as. Cannot be
   *          null.
   * @param wrapped
   *          The Decoder to wrap.
   * @return A ResolvingDecoder configured to resolve <i>writer</i> to
   *         <i>reader</i> from <i>in</i>
   * @throws IOException
   */
  public ResolvingDecoder resolvingDecoder(Schema writer, Schema reader,
      Decoder wrapped) throws IOException {
    return new ResolvingDecoder(writer, reader, wrapped);
  }

  private static class DefaultDecoderFactory extends DecoderFactory {
    @Override
    public DecoderFactory configureDecoderBufferSize(int bufferSize) {
      throw new IllegalArgumentException("This Factory instance is Immutable");
    }
  }
}
