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

import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.internal.MutableForTesting;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.EntryNotFoundException;
import org.apache.geode.cache.Operation;
import org.apache.geode.cache.client.AllConnectionsInUseException;
import org.apache.geode.cache.client.ServerConnectivityException;
import org.apache.geode.cache.client.ServerOperationException;
import org.apache.geode.distributed.internal.ServerLocation;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.cache.EntryEventImpl;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.internal.cache.tier.MessageType;
import org.apache.geode.internal.cache.tier.sockets.Message;
import org.apache.geode.internal.cache.tier.sockets.Part;
import org.apache.geode.internal.cache.versions.VersionTag;
import org.apache.geode.internal.logging.LogService;

/**
 * Does a region destroy on a server
 *
 * @since GemFire 5.7
 */
public class DestroyOp {

  private static final Logger logger = LogService.getLogger();

  public static final int HAS_VERSION_TAG = 0x01;

  public static final int HAS_ENTRY_NOT_FOUND_PART = 0x02;

  /**
   * Does a region entry destroy on a server using connections from the given pool to communicate
   * with the server.
   *
   * @param pool the pool to use to communicate with the server.
   * @param region the region to do the entry destroy on
   * @param key the entry key to do the destroy on
   * @param event the event for this destroy operation
   * @param callbackArg an optional callback arg to pass to any cache callbacks
   */
  public static Object execute(ExecutablePool pool, LocalRegion region, Object key,
      Object expectedOldValue, Operation operation, EntryEventImpl event, Object callbackArg,
      boolean prSingleHopEnabled) {
    if (logger.isDebugEnabled()) {
      logger.debug("Preparing DestroyOp for {} operation={}", key, operation);
    }
    DestroyOpImpl op = new DestroyOpImpl(region, key, expectedOldValue, operation, event,
        callbackArg, prSingleHopEnabled);
    if (prSingleHopEnabled) {
      ClientMetadataService cms = region.getCache().getClientMetadataService();
      ServerLocation server =
          cms.getBucketServerLocation(region, Operation.DESTROY, key, null, callbackArg);
      if (server != null) {
        try {
          PoolImpl poolImpl = (PoolImpl) pool;
          boolean onlyUseExistingCnx = ((poolImpl.getMaxConnections() != -1
              && poolImpl.getConnectionCount() >= poolImpl.getMaxConnections()) ? true : false);
          op.setAllowDuplicateMetadataRefresh(!onlyUseExistingCnx);
          return pool.executeOn(server, op, true, onlyUseExistingCnx);
        } catch (AllConnectionsInUseException e) {
        } catch (ServerConnectivityException e) {
          if (e instanceof ServerOperationException) {
            throw e; // fixed 44656
          }
          cms.removeBucketServerLocation(server);
        }
      }
    }
    return pool.execute(op);
  }

  /**
   * Does a region entry destroy on a server using the given connection to communicate with the
   * server.
   *
   * @param con the connection to use to send to the server
   * @param pool the pool to use to communicate with the server.
   * @param region the region to do the entry destroy on
   * @param key the entry key to do the destroy on
   * @param event the event for this destroy operation
   * @param callbackArg an optional callback arg to pass to any cache callbacks
   */
  public static void execute(Connection con, ExecutablePool pool, String region, Object key,
      Object expectedOldValue, Operation operation, EntryEventImpl event, Object callbackArg) {
    AbstractOp op = new DestroyOpImpl(region, key, expectedOldValue, operation, event, callbackArg);
    pool.executeOn(con, op);
  }

  /** this is set if a response is received indicating that the entry was not found on the server */
  @MutableForTesting
  public static boolean TEST_HOOK_ENTRY_NOT_FOUND;

  private DestroyOp() {
    // no instances allowed
  }

  private static class DestroyOpImpl extends AbstractOp {

    Object key = null;

    private LocalRegion region;

    private Operation operation;

    private boolean prSingleHopEnabled = false;

    private EntryEventImpl event;

    private Object callbackArg;

    /**
     * @throws org.apache.geode.SerializationException if serialization fails
     */
    public DestroyOpImpl(LocalRegion region, Object key, Object expectedOldValue,
        Operation operation, EntryEventImpl event, Object callbackArg, boolean prSingleHopEnabled) {
      super(MessageType.DESTROY, callbackArg != null ? 6 : 5);
      this.key = key;
      this.region = region;
      this.operation = operation;
      this.prSingleHopEnabled = prSingleHopEnabled;
      this.callbackArg = callbackArg;
      this.event = event;
      getMessage().addStringPart(region.getFullPath(), true);
      getMessage().addStringOrObjPart(key);
      getMessage().addObjPart(expectedOldValue);
      getMessage().addBytePart(operation.ordinal);
      getMessage().addBytesPart(event.getEventId().calcBytes());
      if (callbackArg != null) {
        getMessage().addObjPart(callbackArg);
      }
    }


    public DestroyOpImpl(String region, Object key, Object expectedOldValue, Operation operation,
        EntryEventImpl event, Object callbackArg) {
      super(MessageType.DESTROY, callbackArg != null ? 6 : 5);
      this.key = key;
      this.event = event;
      this.callbackArg = callbackArg;
      getMessage().addStringPart(region, true);
      getMessage().addStringOrObjPart(key);
      getMessage().addObjPart(expectedOldValue);
      getMessage().addBytePart(operation.ordinal);
      getMessage().addBytesPart(event.getEventId().calcBytes());
      if (callbackArg != null) {
        getMessage().addObjPart(callbackArg);
      }
    }

    @Override
    protected Object processResponse(Message msg) throws Exception {
      throw new UnsupportedOperationException();
    }


    @Override
    protected Object processResponse(Message msg, Connection con) throws Exception {
      processAck(msg, "destroy");
      boolean isReply = (msg.getMessageType() == MessageType.REPLY);
      int partIdx = 0;
      int flags = 0;
      if (isReply) {
        flags = msg.getPart(partIdx++).getInt();
        if ((flags & HAS_VERSION_TAG) != 0) {
          VersionTag tag = (VersionTag) msg.getPart(partIdx++).getObject();
          // we use the client's ID since we apparently don't track the server's ID in connections
          tag.replaceNullIDs((InternalDistributedMember) con.getEndpoint().getMemberId());
          this.event.setVersionTag(tag);
          if (logger.isDebugEnabled()) {
            logger.debug("received Destroy response with {}", tag);
          }
        } else if (logger.isDebugEnabled()) {
          logger.debug("received Destroy response with no version tag");
        }
      }
      if (prSingleHopEnabled) {
        Part part = msg.getPart(partIdx++);
        byte[] bytesReceived = part.getSerializedForm();
        if (bytesReceived[0] != ClientMetadataService.INITIAL_VERSION
            && bytesReceived.length == ClientMetadataService.SIZE_BYTES_ARRAY_RECEIVED) {
          if (this.region != null) {
            try {
              ClientMetadataService cms = region.getCache().getClientMetadataService();
              int myVersion =
                  cms.getMetaDataVersion(region, Operation.UPDATE, key, null, callbackArg);
              if (myVersion != bytesReceived[0] || isAllowDuplicateMetadataRefresh()) {
                cms.scheduleGetPRMetaData(region, false, bytesReceived[1]);
              }
            } catch (CacheClosedException e) {
              return null;
            }
          }
        }
      } else {
        partIdx++; // skip OK byte
      }
      boolean entryNotFound = false;
      if (msg.getMessageType() == MessageType.REPLY && (flags & HAS_ENTRY_NOT_FOUND_PART) != 0) {
        entryNotFound = (msg.getPart(partIdx++).getInt() == 1);
        if (logger.isDebugEnabled() && (flags & HAS_ENTRY_NOT_FOUND_PART) != 0) {
          logger.debug("destroy response has entryNotFound={}", entryNotFound);
        }
        if (entryNotFound) {
          TEST_HOOK_ENTRY_NOT_FOUND = true;
        }
      }
      if (this.operation == Operation.REMOVE && entryNotFound) {
        if (logger.isDebugEnabled()) {
          logger.debug("received REMOVE response from server with entryNotFound={}", entryNotFound);
        }
        return new EntryNotFoundException(
            "entry not found with expected value");
      }
      return null;
    }

    @Override
    protected boolean isErrorResponse(int msgType) {
      return msgType == MessageType.DESTROY_DATA_ERROR;
    }

    @Override
    protected long startAttempt(ConnectionStats stats) {
      return stats.startDestroy();
    }

    @Override
    protected void endSendAttempt(ConnectionStats stats, long start) {
      stats.endDestroySend(start, hasFailed());
    }

    @Override
    protected void endAttempt(ConnectionStats stats, long start) {
      stats.endDestroy(start, hasTimedOut(), hasFailed());
    }

    @Override
    public String toString() {
      return "DestroyOp:" + key;
    }
  }
}
