/*
 * 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.tier.sockets.command;

import java.io.IOException;

import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.operations.GetOperationContext;
import org.apache.geode.cache.operations.internal.GetOperationContextImpl;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.internal.cache.tier.Command;
import org.apache.geode.internal.cache.tier.MessageType;
import org.apache.geode.internal.cache.tier.sockets.BaseCommand;
import org.apache.geode.internal.cache.tier.sockets.ChunkedMessage;
import org.apache.geode.internal.cache.tier.sockets.Message;
import org.apache.geode.internal.cache.tier.sockets.ObjectPartList;
import org.apache.geode.internal.cache.tier.sockets.Part;
import org.apache.geode.internal.cache.tier.sockets.ServerConnection;
import org.apache.geode.internal.cache.tier.sockets.VersionedObjectList;
import org.apache.geode.internal.cache.versions.VersionTag;
import org.apache.geode.internal.offheap.OffHeapHelper;
import org.apache.geode.internal.offheap.annotations.Retained;
import org.apache.geode.internal.security.AuthorizeRequest;
import org.apache.geode.internal.security.AuthorizeRequestPP;
import org.apache.geode.internal.security.SecurityService;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.security.NotAuthorizedException;
import org.apache.geode.security.ResourcePermission.Operation;
import org.apache.geode.security.ResourcePermission.Resource;

/**
 * Initial version copied from GetAll70.java r48777.
 */
public class GetAllWithCallback extends BaseCommand {
  private static final Logger logger = LogService.getLogger();

  @Immutable
  private static final GetAllWithCallback singleton = new GetAllWithCallback();

  public static Command getCommand() {
    return singleton;
  }

  @Override
  public void cmdExecute(final Message clientMessage, final ServerConnection serverConnection,
      final SecurityService securityService, long start) throws IOException, InterruptedException {
    Part regionNamePart = null, keysPart = null, callbackPart = null;
    String regionName = null;
    Object[] keys = null;
    Object callback = null;
    serverConnection.setAsTrue(REQUIRES_RESPONSE);
    serverConnection.setAsTrue(REQUIRES_CHUNKED_RESPONSE);
    int partIdx = 0;

    // Retrieve the region name from the message parts
    regionNamePart = clientMessage.getPart(partIdx++);
    regionName = regionNamePart.getCachedString();

    // Retrieve the keys array from the message parts
    keysPart = clientMessage.getPart(partIdx++);
    try {
      keys = (Object[]) keysPart.getObject();
    } catch (Exception e) {
      writeChunkedException(clientMessage, e, serverConnection);
      serverConnection.setAsTrue(RESPONDED);
      return;
    }
    callbackPart = clientMessage.getPart(partIdx++);
    try {
      callback = callbackPart.getObject();
    } catch (Exception e) {
      writeChunkedException(clientMessage, e, serverConnection);
      serverConnection.setAsTrue(RESPONDED);
      return;
    }

    if (logger.isDebugEnabled()) {
      StringBuilder buffer = new StringBuilder();
      buffer.append(serverConnection.getName()).append(": Received getAll request (")
          .append(clientMessage.getPayloadLength()).append(" bytes) from ")
          .append(serverConnection.getSocketString()).append(" for region ").append(regionName)
          .append(" with callback ").append(callback).append(" keys ");
      if (keys != null) {
        for (int i = 0; i < keys.length; i++) {
          buffer.append(keys[i]).append(" ");
        }
      } else {
        buffer.append("NULL");
      }
      logger.debug(buffer.toString());
    }

    // Process the getAll request
    if (regionName == null) {
      String message = null;
      // if (regionName == null) (can only be null)
      {
        message = "The input region name for the getAll request is null";
      }
      logger.warn("{} : {}",
          new Object[] {serverConnection.getName(), message});
      writeChunkedErrorResponse(clientMessage, MessageType.GET_ALL_DATA_ERROR, message,
          serverConnection);
      serverConnection.setAsTrue(RESPONDED);
      return;
    }
    LocalRegion region = (LocalRegion) serverConnection.getCache().getRegion(regionName);
    if (region == null) {
      String reason = " was not found during getAll request";
      writeRegionDestroyedEx(clientMessage, regionName, reason, serverConnection);
      serverConnection.setAsTrue(RESPONDED);
      return;
    }
    // Send header
    ChunkedMessage chunkedResponseMsg = serverConnection.getChunkedResponseMessage();
    chunkedResponseMsg.setMessageType(MessageType.RESPONSE);
    chunkedResponseMsg.setTransactionId(clientMessage.getTransactionId());
    chunkedResponseMsg.sendHeader();

    // Send chunk response
    try {
      fillAndSendGetAllResponseChunks(region, regionName, keys, serverConnection, callback,
          securityService);
      serverConnection.setAsTrue(RESPONDED);
    } catch (Exception e) {
      // If an interrupted exception is thrown , rethrow it
      checkForInterrupt(serverConnection, e);

      // Otherwise, write an exception message and continue
      writeChunkedException(clientMessage, e, serverConnection);
      serverConnection.setAsTrue(RESPONDED);
      return;
    }
  }

  private void fillAndSendGetAllResponseChunks(Region region, String regionName, Object[] keys,
      ServerConnection servConn, Object callback, SecurityService securityService)
      throws IOException {

    assert keys != null;
    int numKeys = keys.length;
    VersionedObjectList values = new VersionedObjectList(MAXIMUM_CHUNK_SIZE, false,
        region.getAttributes().getConcurrencyChecksEnabled(), false);
    try {
      AuthorizeRequest authzRequest = servConn.getAuthzRequest();
      AuthorizeRequestPP postAuthzRequest = servConn.getPostAuthzRequest();
      Get70 request = (Get70) Get70.getCommand();
      for (int i = 0; i < numKeys; i++) {
        // Send the intermediate chunk if necessary
        if (values.size() == MAXIMUM_CHUNK_SIZE) {
          // Send the chunk and clear the list
          sendGetAllResponseChunk(region, values, false, servConn);
          values.clear();
        }

        Object key;
        boolean keyNotPresent = false;
        key = keys[i];
        if (logger.isDebugEnabled()) {
          logger.debug("{}: Getting value for key={}", servConn.getName(), key);
        }
        // Determine if the user authorized to get this key
        GetOperationContext getContext = null;
        if (authzRequest != null) {
          try {
            getContext = authzRequest.getAuthorize(regionName, key, callback);
            if (logger.isDebugEnabled()) {
              logger.debug("{}: Passed GET pre-authorization for key={}", servConn.getName(), key);
            }
          } catch (NotAuthorizedException ex) {
            logger.warn(String.format(
                "%s: Caught the following exception attempting to get value for key=%s",
                new Object[] {servConn.getName(), key}),
                ex);
            values.addExceptionPart(key, ex);
            continue;
          }
        }

        try {
          securityService.authorize(Resource.DATA, Operation.READ, regionName, key);
        } catch (NotAuthorizedException ex) {
          logger.warn(
              String.format("%s: Caught the following exception attempting to get value for key=%s",
                  new Object[] {servConn.getName(), key}),
              ex);
          values.addExceptionPart(key, ex);
          continue;
        }

        // Get the value and update the statistics. Do not deserialize
        // the value if it is a byte[].
        // Getting a value in serialized form is pretty nasty. I split this out
        // so the logic can be re-used by the CacheClientProxy.
        Get70.Entry entry = request.getEntry(region, key, callback, servConn);
        @Retained
        final Object originalData = entry.value;
        Object data = originalData;
        if (logger.isDebugEnabled()) {
          logger.debug("retrieved key={} {}", key, entry);
        }
        boolean addedToValues = false;
        try {
          boolean isObject = entry.isObject;
          VersionTag versionTag = entry.versionTag;
          keyNotPresent = entry.keyNotPresent;

          if (postAuthzRequest != null) {
            try {
              getContext =
                  postAuthzRequest.getAuthorize(regionName, key, data, isObject, getContext);
              GetOperationContextImpl gci = (GetOperationContextImpl) getContext;
              Object newData = gci.getRawValue();
              if (newData != data) {
                // user changed the value
                isObject = getContext.isObject();
                data = newData;
              }
            } catch (NotAuthorizedException ex) {
              logger.warn(String.format(
                  "%s: Caught the following exception attempting to get value for key=%s",
                  new Object[] {servConn.getName(), key}),
                  ex);
              values.addExceptionPart(key, ex);
              continue;
            } finally {
              if (getContext != null) {
                ((GetOperationContextImpl) getContext).release();
              }
            }
          }
          // Add the entry to the list that will be returned to the client
          if (keyNotPresent) {
            values.addObjectPartForAbsentKey(key, data, versionTag);
            addedToValues = true;
          } else {
            values.addObjectPart(key, data, isObject, versionTag);
            addedToValues = true;
          }
        } finally {
          if (!addedToValues || data != originalData) {
            OffHeapHelper.release(originalData);
          }
        }
      }

      // Send the last chunk even if the list is of zero size.
      sendGetAllResponseChunk(region, values, true, servConn);
      servConn.setAsTrue(RESPONDED);
    } finally {
      values.release();
    }
  }


  private static void sendGetAllResponseChunk(Region region, ObjectPartList list, boolean lastChunk,
      ServerConnection servConn) throws IOException {
    ChunkedMessage chunkedResponseMsg = servConn.getChunkedResponseMessage();
    chunkedResponseMsg.setNumberOfParts(1);
    chunkedResponseMsg.setLastChunk(lastChunk);
    chunkedResponseMsg.addObjPartNoCopying(list);

    if (logger.isDebugEnabled()) {
      logger.debug("{}: Sending {} getAll response chunk for region={}{}", servConn.getName(),
          (lastChunk ? " last " : " "), region.getFullPath(), (logger.isTraceEnabled()
              ? " values=" + list + " chunk=<" + chunkedResponseMsg + ">" : ""));
    }

    chunkedResponseMsg.sendChunk(servConn);
  }

}
