/*
 * 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.geode.pdx.internal;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.PrintStream;

import org.apache.geode.DataSerializable;
import org.apache.geode.DataSerializer;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.Version;
import org.apache.geode.pdx.FieldType;

public class PdxField implements DataSerializable, Comparable<PdxField> {

  private static final long serialVersionUID = -1095459461236458274L;

  private String fieldName;
  private int fieldIndex;
  private int varLenFieldSeqId;
  private FieldType type;
  /**
   * If >= 0 then it is relative to the first byte of field data. Otherwise it is relative to the
   * base determined by vlfOffsetIndex.
   */
  private int relativeOffset;

  /**
   * if >= 0 then it is the index of the vlfOffsets that this field should use as its base to find
   * its data. If < 0 then it should be -1 which means the base is the first byte after the last
   * byte of field data.
   */
  private int vlfOffsetIndex;

  private boolean identityField;

  /**
   * Set to true by the pdx delete-field gfsh command
   *
   * @since GemFire 8.1
   */
  private boolean deleted;

  public PdxField() {}

  public PdxField(String fieldName, int index, int varId, FieldType type, boolean identityField) {
    this.fieldName = fieldName;
    this.fieldIndex = index;
    this.varLenFieldSeqId = varId;
    this.type = type;
    this.identityField = identityField;
  }

  /**
   * Used by {@link PdxInstanceImpl#equals(Object)} to act as if it has a field whose value is
   * always the default.
   */
  protected PdxField(PdxField other) {
    this.fieldName = other.fieldName;
    this.fieldIndex = other.fieldIndex;
    this.varLenFieldSeqId = other.varLenFieldSeqId;
    this.type = other.type;
    this.identityField = other.identityField;
    this.deleted = other.deleted;
  }

  public String getFieldName() {
    return this.fieldName;
  }

  public int getFieldIndex() {
    return this.fieldIndex;
  }

  public int getVarLenFieldSeqId() {
    return this.varLenFieldSeqId;
  }

  public boolean isVariableLengthType() {
    return !this.type.isFixedWidth();
  }

  public FieldType getFieldType() {
    return this.type;
  }

  public int getRelativeOffset() {
    return this.relativeOffset;
  }

  public void setRelativeOffset(int relativeOffset) {
    this.relativeOffset = relativeOffset;
  }

  public int getVlfOffsetIndex() {
    return this.vlfOffsetIndex;
  }

  public void setVlfOffsetIndex(int vlfOffsetIndex) {
    this.vlfOffsetIndex = vlfOffsetIndex;
  }

  public void setIdentityField(boolean identityField) {
    this.identityField = identityField;
  }

  public boolean isIdentityField() {
    return this.identityField;
  }

  public void setDeleted(boolean v) {
    this.deleted = v;
  }

  public boolean isDeleted() {
    return this.deleted;
  }

  private static final byte IDENTITY_BIT = 1;
  private static final byte DELETED_BIT = 2;

  @Override
  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
    this.fieldName = DataSerializer.readString(in);
    this.fieldIndex = in.readInt();
    this.varLenFieldSeqId = in.readInt();
    this.type = DataSerializer.readEnum(FieldType.class, in);
    this.relativeOffset = in.readInt();
    this.vlfOffsetIndex = in.readInt();
    {
      byte bits = in.readByte();
      this.identityField = (bits & IDENTITY_BIT) != 0;
      this.deleted = (bits & DELETED_BIT) != 0;
    }
  }

  @Override
  public void toData(DataOutput out) throws IOException {
    DataSerializer.writeString(this.fieldName, out);
    out.writeInt(this.fieldIndex);
    out.writeInt(this.varLenFieldSeqId);
    DataSerializer.writeEnum(this.type, out);
    out.writeInt(this.relativeOffset);
    out.writeInt(this.vlfOffsetIndex);
    {
      // pre 8.1 we wrote a single boolean
      // 8.1 and after we write a byte whose bits are:
      // 1: identityField
      // 2: deleted
      byte bits = 0;
      if (this.identityField) {
        bits |= IDENTITY_BIT;
      }
      // Note that this code attempts to only set the DELETED_BIT
      // if serializing for 8.1 or later.
      // But in some cases 8.1 serialized data may be sent to a pre 8.1 member.
      // In that case if this bit is set it will cause the pre 8.1 member
      // to set identityField to true.
      // For this reason the pdx delete-field command should only be used after
      // all member have been upgraded to 8.1 or later.
      Version sourceVersion = InternalDataSerializer.getVersionForDataStream(out);
      if (sourceVersion.compareTo(Version.GFE_81) >= 0) {
        if (this.deleted) {
          bits |= DELETED_BIT;
        }
      }
      out.writeByte(bits);
    }
  }

  @Override
  public int hashCode() {
    int hash = 1;
    if (fieldName != null) {
      hash = hash * 31 + fieldName.hashCode();
    }
    if (type != null) {
      hash = hash * 31 + type.hashCode();
    }

    return hash;
  }

  // We don't compare the offsets here, because
  // this method is to see if two different PDXTypes
  // have equivalent fields. See PdxReaderImpl.equals.
  @Override
  public boolean equals(Object other) {
    if (other == this) {
      return true;
    }
    if (other == null || !(other instanceof PdxField)) {
      return false;
    }
    PdxField otherVFT = (PdxField) other;

    if (otherVFT.fieldName == null) {
      return false;
    }

    if (otherVFT.fieldName.equals(this.fieldName) && this.isDeleted() == otherVFT.isDeleted()
        && this.type.equals(otherVFT.type)) {
      return true;
    }
    return false;
  }

  @Override
  public String toString() {
    return this.fieldName + ":" + this.type + (isDeleted() ? ":DELETED" : "")
        + (isIdentityField() ? ":identity" : "") + ":" + this.fieldIndex
        + ((this.varLenFieldSeqId > 0) ? (":" + this.varLenFieldSeqId) : "")
        + ":idx0(relativeOffset)=" + this.relativeOffset + ":idx1(vlfOffsetIndex)="
        + this.vlfOffsetIndex;
  }

  public String getTypeIdString() {
    return getFieldType().toString();
  }

  @Override
  public int compareTo(PdxField o) {
    return getFieldName().compareTo(o.getFieldName());
  }

  public void toStream(PrintStream printStream) {
    printStream.print("    ");
    printStream.print(getFieldType());
    printStream.print(' ');
    printStream.print(this.getFieldName());
    printStream.print(';');
    if (isIdentityField()) {
      printStream.print(" // identity");
    }
    if (isDeleted()) {
      printStream.print(" // DELETED");
    }

    printStream.println();
  }
}
