/*
 * 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.drill.exec.vector.accessor.writer;

import java.lang.reflect.Array;
import java.math.BigDecimal;

import org.apache.drill.exec.record.metadata.ColumnMetadata;
import org.apache.drill.exec.vector.accessor.ColumnWriterIndex;
import org.apache.drill.exec.vector.accessor.ScalarWriter;
import org.apache.drill.exec.vector.accessor.writer.AbstractArrayWriter.BaseArrayWriter;
import org.apache.drill.exec.vector.accessor.writer.AbstractScalarWriterImpl.ScalarObjectWriter;
import org.apache.drill.exec.vector.complex.RepeatedValueVector;
import org.joda.time.Period;

/**
 * Writer for a column that holds an array of scalars. This writer manages
 * the array itself. A type-specific child writer manages the elements within
 * the array. The overall row index (usually) provides the index into
 * the offset vector. An array-specific element index provides the index
 * into elements.
 * <p>
 * This class manages the offset vector directly. Doing so saves one read and
 * one write to direct memory per element value.
 * <p>
 * Provides generic write methods for testing and other times when
 * convenience is more important than speed.
 * <p>
 * The scalar writer for array-valued columns appends values: once a value
 * is written, it cannot be changed. As a result, writer methods have no item index;
 * each set advances the array to the next position. This is an abstract base class;
 * subclasses are generated for each repeated value vector type.
 */
public class ScalarArrayWriter extends BaseArrayWriter {

  /**
   * For scalar arrays, incrementing the element index and
   * committing the current value is done automatically since
   * there is exactly one value per array element.
   */
  public class ScalarElementWriterIndex extends ArrayElementWriterIndex {

    @Override
    public final void nextElement() { next(); }

    @Override
    public final void prevElement() { prev(); }
  }

  private final ScalarWriter elementWriter;

  public ScalarArrayWriter(ColumnMetadata schema,
      RepeatedValueVector vector, BaseScalarWriter baseElementWriter) {
    super(schema, vector.getOffsetVector(),
        new ScalarObjectWriter(baseElementWriter));

    // Save the writer from the scalar object writer created above
    // which may have wrapped the element writer in a type convertor.
    this.elementWriter = elementObjWriter.scalar();
  }

  public static ArrayObjectWriter build(ColumnMetadata schema,
      RepeatedValueVector repeatedVector, BaseScalarWriter baseElementWriter) {
    return new ArrayObjectWriter(
        new ScalarArrayWriter(schema, repeatedVector, baseElementWriter));
  }

  @Override
  public void bindIndex(ColumnWriterIndex index) {
    elementIndex = new ScalarElementWriterIndex();
    super.bindIndex(index);
    elementObjWriter.events().bindIndex(elementIndex);
  }

  @Override
  public void save() {
    // No-op: done when writing each scalar value
    // May be called, however, by code that also supports
    // lists as a list does require an explicit save.
  }

  /**
   * Set a repeated vector based on a Java array of the proper
   * type. This function involves parsing the array type and so is
   * suitable only for test code. The array can be either a primitive
   * ({@code int [], say}) or a typed array of boxed values
   * ({@code Integer[], say}).
   */
  @Override
  public void setObject(Object array) {

    // Accept an empty array (of any type) to mean
    // an empty array of the type of this writer.
    if (array == null || Array.getLength(array) == 0) {

      // Assume null means a 0-element array since Drill does
      // not support null for the whole array.
      return;
    }
    final String objClass = array.getClass().getName();
    if (! objClass.startsWith("[")) {
      throw new IllegalArgumentException(
          String.format("Argument must be an array. Column `%s`, value = %s",
              schema().name(), array.toString()));
    }

    // Figure out type
    final char second = objClass.charAt(1);
    switch ( second ) {
    case  '[':

      // bytes is represented as an array of byte arrays.
      final char third = objClass.charAt(2);
      switch (third) {
      case 'B':
        setBytesArray((byte[][]) array);
        break;
      default:
        throw new IllegalArgumentException(
            String.format("Unknown Java array type: %s, for column `%s`",
                objClass, schema().name()));
      }
      break;
    case  'B':
      setByteArray((byte[]) array);
      break;
    case  'S':
      setShortArray((short[]) array);
      break;
    case  'I':
      setIntArray((int[]) array);
      break;
    case  'J':
      setLongArray((long[]) array);
      break;
    case  'F':
      setFloatArray((float[]) array);
      break;
    case  'D':
      setDoubleArray((double[]) array);
      break;
    case  'Z':
      setBooleanArray((boolean[]) array);
      break;
    case 'L':
      final int posn = objClass.indexOf(';');

      // If the array is of type Object, then we have no type info.
      final String memberClassName = objClass.substring(2, posn);
      if (memberClassName.equals(String.class.getName())) {
        setStringArray((String[]) array);
      } else if (memberClassName.equals(Period.class.getName())) {
        setPeriodArray((Period[]) array);
      } else if (memberClassName.equals(BigDecimal.class.getName())) {
        setBigDecimalArray((BigDecimal[]) array);
      } else if (memberClassName.equals(Integer.class.getName())) {
        setIntObjectArray((Integer[]) array);
      } else if (memberClassName.equals(Long.class.getName())) {
        setLongObjectArray((Long[]) array);
      } else if (memberClassName.equals(Double.class.getName())) {
        setDoubleObjectArray((Double[]) array);
      } else if (memberClassName.equals(Float.class.getName())) {
        setFloatObjectArray((Float[]) array);
      } else if (memberClassName.equals(Short.class.getName())) {
        setShortObjectArray((Short[]) array);
      } else if (memberClassName.equals(Byte.class.getName())) {
        setByteObjectArray((Byte[]) array);
      } else if (memberClassName.equals(Boolean.class.getName())) {
        setBooleanObjectArray((Boolean[]) array);
      } else if (memberClassName.equals(Object.class.getName())) {
        setObjectArray((Object[]) array);
      } else {
        throw new IllegalArgumentException( "Unknown Java array type: " + memberClassName );
      }
      break;
    default:
      throw new IllegalArgumentException( "Unknown Java array type: " + objClass );
    }
  }

  public void setObjectArray(Object[] value) {
    for (int i = 0; i < value.length; i++) {
      final Object element = value[i];
      if (element != null) {
        elementWriter.setObject(element);
      }
    }
  }

  public void setBooleanArray(boolean[] value) {
    for (int i = 0; i < value.length; i++) {
      elementWriter.setInt(value[i] ? 1 : 0);
    }
  }

  public void setBooleanObjectArray(Boolean[] value) {
    for (int i = 0; i < value.length; i++) {
      final Boolean element = value[i];
      if (element != null) {
        elementWriter.setBoolean(element);
      }
    }
  }

  public void setBytesArray(byte[][] value) {
    for (int i = 0; i < value.length; i++) {
      elementWriter.setBytes(value[i], value[i].length);
    }
  }

  public void setByteArray(byte[] value) {
    for (int i = 0; i < value.length; i++) {
      elementWriter.setInt(value[i]);
    }
  }

  public void setByteObjectArray(Byte[] value) {
    for (int i = 0; i < value.length; i++) {
      final Byte element = value[i];
      if (element != null) {
        elementWriter.setInt(element);
      }
    }
  }

  public void setShortArray(short[] value) {
    for (int i = 0; i < value.length; i++) {
      elementWriter.setInt(value[i]);
    }
  }

  public void setShortObjectArray(Short[] value) {
    for (int i = 0; i < value.length; i++) {
      final Short element = value[i];
      if (element != null) {
        elementWriter.setInt(element);
      }
    }
  }

  public void setIntArray(int[] value) {
    for (int i = 0; i < value.length; i++) {
      elementWriter.setInt(value[i]);
    }
  }

  public void setIntObjectArray(Integer[] value) {
    for (int i = 0; i < value.length; i++) {
      final Integer element = value[i];
      if (element != null) {
        elementWriter.setInt(element);
      }
    }
  }

  public void setLongArray(long[] value) {
    for (int i = 0; i < value.length; i++) {
      elementWriter.setLong(value[i]);
    }
  }

  public void setLongObjectArray(Long[] value) {
    for (int i = 0; i < value.length; i++) {
      final Long element = value[i];
      if (element != null) {
        elementWriter.setLong(element);
      }
    }
  }

  public void setFloatArray(float[] value) {
    for (int i = 0; i < value.length; i++) {
      elementWriter.setDouble(value[i]);
    }
  }

  public void setFloatObjectArray(Float[] value) {
    for (int i = 0; i < value.length; i++) {
      final Float element = value[i];
      if (element != null) {
        elementWriter.setDouble(element);
      }
    }
  }

  public void setDoubleArray(double[] value) {
    for (int i = 0; i < value.length; i++) {
      elementWriter.setDouble(value[i]);
    }
  }

  public void setDoubleObjectArray(Double[] value) {
    for (int i = 0; i < value.length; i++) {
      final Double element = value[i];
      if (element != null) {
        elementWriter.setDouble(element);
      }
    }
  }

  public void setStringArray(String[] value) {
    for (int i = 0; i < value.length; i++) {
      final String element = value[i];
      if (element != null) {
        elementWriter.setString(element);
      }
    }
  }

  public void setPeriodArray(Period[] value) {
    for (int i = 0; i < value.length; i++) {
      final Period element = value[i];
      if (element != null) {
        elementWriter.setPeriod(element);
      }
    }
  }

  public void setBigDecimalArray(BigDecimal[] value) {
    for (int i = 0; i < value.length; i++) {
      final BigDecimal element = value[i];
      if (element != null) {
        elementWriter.setDecimal(element);
      }
    }
  }
}
