/*
 * 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.
 */
import java.lang.Override;
import java.util.Vector;

import org.apache.drill.exec.vector.AllocationHelper;
import org.apache.drill.exec.vector.ValueVector.Mutator;
import org.apache.drill.exec.vector.complex.IndexHolder;
import org.apache.drill.exec.vector.complex.reader.FieldReader;

<@pp.dropOutputFile />
<#list vv.types as type>
<#list type.minor as minor>
<#list ["", "Nullable", "Repeated"] as mode>
<#assign name = mode + minor.class?cap_first />
<#assign eName = name />
<#assign javaType = (minor.javaType!type.javaType) />
<#assign fields = minor.fields!type.fields />

<@pp.changeOutputFile name="/org/apache/drill/exec/vector/complex/impl/${eName}WriterImpl.java" />
<#include "/@includes/license.ftl" />

package org.apache.drill.exec.vector.complex.impl;

<#include "/@includes/vv_imports.ftl" />

/*
 * This class is generated using FreeMarker on the ${.template_name} template.
 */
@SuppressWarnings("unused")
public class ${eName}WriterImpl extends AbstractFieldWriter {

  private final ${name}Vector.Mutator mutator;
  final ${name}Vector vector;

  public ${eName}WriterImpl(${name}Vector vector, AbstractFieldWriter parent) {
    super(parent);
    this.mutator = vector.getMutator();
    this.vector = vector;
  }

  @Override
  public MaterializedField getField() {
    return vector.getField();
  }

  @Override
  public int getValueCapacity() {
    return vector.getValueCapacity();
  }

  @Override
  public void allocate() {
    vector.allocateNew();
  }

  @Override
  public void close() {
    vector.close();
  }

  @Override
  public void clear() {
    vector.clear();
  }

  <#if mode == "Repeated">
  public void write(${minor.class?cap_first}Holder h) {
    mutator.addSafe(idx(), h);
    vector.getMutator().setValueCount(idx()+1);
  }

  public void write(Nullable${minor.class?cap_first}Holder h) {
    mutator.addSafe(idx(), h);
    vector.getMutator().setValueCount(idx()+1);
  }

  <#if !minor.class?contains("Decimal") || minor.class?contains("VarDecimal")>
  public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
    mutator.addSafe(idx()<#list fields as field><#if field.include!true>, ${field.name}</#if></#list>);
    vector.getMutator().setValueCount(idx() + 1);
  }
  
  </#if>
  <#if minor.class?contains("VarDecimal")>
  public void writeVarDecimal(BigDecimal value) {
    mutator.addSafe(idx(), value.unscaledValue().toByteArray());
    vector.getMutator().setValueCount(idx() + 1);
  }
  </#if>

  public void setPosition(int idx) {
    super.setPosition(idx);
    // calls startNewValue only for the case
    // when it wouldn't override existing data
    if (idx >= vector.getAccessor().getValueCount()) {
      mutator.startNewValue(idx);
    }
  }
  
  <#else>
  public void write(${minor.class}Holder h) {
    mutator.setSafe(idx(), h);
    vector.getMutator().setValueCount(idx()+1);
  }

  public void write(Nullable${minor.class}Holder h) {
    mutator.setSafe(idx(), h);
    vector.getMutator().setValueCount(idx()+1);
  }

  <#if mode == "Nullable">
  public void writeNull() {
    mutator.setNull(idx());
    vector.getMutator().setValueCount(idx() + 1);
  }
  
  </#if>
  <#if !(minor.class == "Decimal9" || minor.class == "Decimal18")>
  public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
    mutator.setSafe(idx()<#if mode == "Nullable">, 1</#if><#list fields as field><#if field.include!true>, ${field.name}</#if></#list>);
    vector.getMutator().setValueCount(idx() + 1);
  }

  <#if minor.class?contains("VarDecimal")>
  public void write${minor.class}(BigDecimal value) {
    mutator.setSafe(idx(), value);
    vector.getMutator().setValueCount(idx() + 1);
  }
  </#if>
  </#if>
  </#if>
}

<@pp.changeOutputFile name="/org/apache/drill/exec/vector/complex/writer/${eName}Writer.java" />
<#include "/@includes/license.ftl" />

package org.apache.drill.exec.vector.complex.writer;

<#include "/@includes/vv_imports.ftl" />
@SuppressWarnings("unused")
public interface ${eName}Writer extends BaseWriter {
  public void write(${minor.class}Holder h);

  <#if !(minor.class == "Decimal9" || minor.class == "Decimal18")>
  public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>);
  </#if>

  <#if minor.class?contains("VarDecimal")>
  public void write${minor.class}(BigDecimal value);
  </#if>
}

</#list>
</#list>
</#list>
