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

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

import org.apache.geode.CopyHelper;
import org.apache.geode.DataSerializer;
import org.apache.geode.cache.Region;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.cache.eviction.EvictableEntry;
import org.apache.geode.internal.lang.StringUtils;
import org.apache.geode.internal.serialization.DataSerializableFixedID;
import org.apache.geode.internal.serialization.DeserializationContext;
import org.apache.geode.internal.serialization.SerializationContext;
import org.apache.geode.internal.serialization.Version;
import org.apache.geode.pdx.PdxInstance;

/**
 * The first time someone asks this instance for its Object it will deserialize the bytes and from
 * then on keep a reference to the deserialized form. So it "prefers deserialization".
 *
 */
public class VMCachedDeserializable implements CachedDeserializable, DataSerializableFixedID {

  /** The cached value */
  private volatile Object value;
  private int valueSize; // only set in constructor or fromData

  /**
   * +PER_OBJECT_OVERHEAD for VMCachedDeserializable object +4 for value field +4 for valueSize
   * field
   */
  static final int MEM_OVERHEAD = PER_OBJECT_OVERHEAD + 4 + 4;

  /**
   * zero-arg constructor for serialization only
   */
  public VMCachedDeserializable() {}

  /**
   * Creates a new instance of <code>VMCachedDeserializable</code>.
   *
   * Note that, in general, instances of this class should be obtained via
   * {@link CachedDeserializableFactory}.
   */
  public VMCachedDeserializable(byte[] serializedValue) {
    if (serializedValue == null)
      throw new NullPointerException(
          "value must not be null");
    this.value = serializedValue;
    this.valueSize = CachedDeserializableFactory.getByteSize(serializedValue);
  }

  VMCachedDeserializable(VMCachedDeserializable cd) {
    this.value = cd.value;
    this.valueSize = cd.valueSize;
  }

  /**
   * Create a new instance with an object and it's size. Note the caller decides if objectSize is
   * the memory size or the serialized size.
   *
   */
  public VMCachedDeserializable(Object object, int objectSize) {
    this.value = object;
    this.valueSize = objectSize;
  }

  @Override
  public Object getDeserializedValue(Region r, RegionEntry re) {
    Object v = this.value;
    if (v instanceof byte[]) {
      // org.apache.geode.internal.cache.GemFireCache.getInstance().getLogger().info("DEBUG
      // getDeserializedValue r=" + r + " re=" + re, new RuntimeException("STACK"));
      EvictableEntry le = null;
      if (re != null) {
        assert r != null;
        if (re instanceof EvictableEntry) {
          le = (EvictableEntry) re;
        }
      }
      if (le != null) {
        if (r instanceof PartitionedRegion) {
          r = ((PartitionedRegion) r).getBucketRegion(re.getKey());
        }
        boolean callFinish = false;
        RegionMap regionMap = null;
        if (r != null) { // fix for bug 44795
          regionMap = ((InternalRegion) r).getRegionMap();
        }
        boolean threadAlreadySynced = Thread.holdsLock(le);
        boolean isCacheListenerInvoked = re.isCacheListenerInvocationInProgress();
        synchronized (le) {
          v = this.value;
          if (!(v instanceof byte[]))
            return v;
          v = EntryEventImpl.deserialize((byte[]) v);
          if (threadAlreadySynced && !isCacheListenerInvoked) {
            // to fix bug 43355 and 43409 don't change the value form
            // if the thread that called us was already synced.
            return v;
          }
          if (!(v instanceof PdxInstance)) {
            this.value = v;
            if (regionMap != null) {
              callFinish = regionMap.beginChangeValueForm(le, this, v);
            }
          }
        }
        if (callFinish && !isCacheListenerInvoked) {
          regionMap.finishChangeValueForm();
        }
      } else {
        // we sync on this so we will only do one deserialize
        synchronized (this) {
          v = this.value;
          if (!(v instanceof byte[]))
            return v;
          v = EntryEventImpl.deserialize((byte[]) v);
          if (!(v instanceof PdxInstance)) {
            this.value = v;
          }
          // ObjectSizer os = null;
          // if (r != null) {
          // EvictionAttributes ea = r.getAttributes().getEvictionAttributes();
          // if (ea != null) {
          // os = ea.getObjectSizer();
          // }
          // int vSize = CachedDeserializableFactory.calcMemSize(v, os, false, false);
          // if (vSize != -1) {
          // int oldSize = this.valueSize;
          // this.valueSize = vSize;
          // if (r instanceof BucketRegion) {
          // BucketRegion br = (BucketRegion)r;
          // br.updateBucketMemoryStats(vSize - oldSize);
          // }
          // // @todo do we need to update some lru stats since the size changed?
          // }
          // // If vSize == -1 then leave valueSize as is which is the serialized size.
        }
      }
    }
    return v;
  }

  @Override
  public Object getDeserializedForReading() {
    Object v = this.value;
    if (v instanceof byte[]) {
      return EntryEventImpl.deserialize((byte[]) v);
    } else {
      return v;
    }
  }

  @Override
  public Object getDeserializedWritableCopy(Region r, RegionEntry re) {
    Object v = this.value;
    if (v instanceof byte[]) {
      Object result = EntryEventImpl.deserialize((byte[]) v);
      if (CopyHelper.isWellKnownImmutableInstance(result) && !(result instanceof PdxInstance)) {
        // Since it is immutable go ahead and change the form
        // since we can return the immutable instance each time.
        result = getDeserializedValue(r, re);
      }
      return result;
    } else {
      return CopyHelper.copy(v);
    }
  }

  /**
   * Return the serialized value as a byte[]
   */
  @Override
  public byte[] getSerializedValue() {
    Object v = this.value;
    if (v instanceof byte[])
      return (byte[]) v;
    return EntryEventImpl.serialize(v);
  }

  /**
   * Return current value regardless of whether it is serialized or deserialized: if it was
   * serialized than it is a byte[], otherwise it is not a byte[].
   */
  @Override
  public Object getValue() {
    return this.value;
  }

  @Override
  public int getSizeInBytes() {
    return MEM_OVERHEAD + this.valueSize;
  }

  @Override
  public int getValueSizeInBytes() {
    return valueSize;
  }

  @Override
  public int getDSFID() {
    return VM_CACHED_DESERIALIZABLE;
  }

  @Override
  public void fromData(DataInput in,
      DeserializationContext context) throws IOException, ClassNotFoundException {
    // fix for bug 38309
    byte[] bytes = DataSerializer.readByteArray(in);
    this.valueSize = bytes.length;
    this.value = bytes;
  }

  @Override
  public void toData(DataOutput out,
      SerializationContext context) throws IOException {
    // fix for bug 38309
    DataSerializer.writeObjectAsByteArray(getValue(), out);
  }

  String getShortClassName() {
    String cname = getClass().getName();
    return cname.substring(getClass().getPackage().getName().length() + 1);
  }

  @Override
  public String toString() {
    return getShortClassName() + "@" + this.hashCode();
  }

  @Override
  public void writeValueAsByteArray(DataOutput out) throws IOException {
    toData(out, InternalDataSerializer.createSerializationContext(out));
  }

  @Override
  public void fillSerializedValue(BytesAndBitsForCompactor wrapper, byte userBits) {
    Object v = this.value;
    if (v instanceof byte[]) {
      wrapper.setData((byte[]) v, userBits, ((byte[]) v).length,
          false /* Not Reusable as it refers to underlying value */);
    } else {
      EntryEventImpl.fillSerializedValue(wrapper, v, userBits);
    }

  }

  @Override
  public String getStringForm() {
    try {
      return StringUtils.forceToString(getDeserializedForReading());
    } catch (RuntimeException ex) {
      return "Could not convert object to string because " + ex;
    }
  }

  @Override
  public Version[] getSerializationVersions() {
    return null;
  }

  @Override
  public boolean isSerialized() {
    return true;
  }

  @Override
  public boolean usesHeapForStorage() {
    return true;
  }
}
