/*
 * 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.rest.internal.web.controllers;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.apache.logging.log4j.Logger;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import org.apache.geode.cache.LowMemoryException;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.execute.Execution;
import org.apache.geode.cache.execute.FunctionException;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.internal.cache.InternalRegion;
import org.apache.geode.internal.cache.execute.util.FindRestEnabledServersFunction;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.rest.internal.web.controllers.support.RestServersResultCollector;
import org.apache.geode.rest.internal.web.exception.GemfireRestException;
import org.apache.geode.rest.internal.web.util.ArrayUtils;
import org.apache.geode.rest.internal.web.util.JSONUtils;

/**
 * The CommonCrudController serves REST Requests related to listing regions, listing keys in region,
 * delete keys or delete all data in region.
 *
 * @since GemFire 8.0
 */
@SuppressWarnings("unused")
public abstract class CommonCrudController extends AbstractBaseController {

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

  /**
   * List all available resources (Regions) in the GemFire cluster
   *
   * @return JSON document containing result
   */
  @RequestMapping(method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
  @ApiOperation(value = "list all resources (Regions)",
      notes = "List all available resources (Regions) in the Geode cluster")
  @ApiResponses({@ApiResponse(code = 200, message = "OK."),
      @ApiResponse(code = 401, message = "Invalid Username or Password."),
      @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
      @ApiResponse(code = 500, message = "GemFire throws an error or exception.")})
  @PreAuthorize("@securityService.authorize('DATA', 'READ')")
  public ResponseEntity<?> regions() {
    logger.debug("Listing all resources (Regions) in Geode...");
    final HttpHeaders headers = new HttpHeaders();
    headers.setLocation(toUri());
    final Set<Region<?, ?>> regions = new HashSet<>();
    for (InternalRegion region : getCache().getApplicationRegions()) {
      regions.add(region);
    }
    String listRegionsAsJson = JSONUtils.formulateJsonForListRegions(regions, "regions");
    return new ResponseEntity<>(listRegionsAsJson, headers, HttpStatus.OK);
  }

  /**
   * List all keys for the given region in the GemFire cluster
   *
   * @param region gemfire region
   * @return JSON document containing result
   */
  @RequestMapping(method = RequestMethod.GET, value = "/{region}/keys",
      produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
  @ApiOperation(value = "list all keys", notes = "List all keys in region")
  @ApiResponses({@ApiResponse(code = 200, message = "OK"),
      @ApiResponse(code = 401, message = "Invalid Username or Password."),
      @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
      @ApiResponse(code = 404, message = "Region does not exist"),
      @ApiResponse(code = 500, message = "GemFire throws an error or exception")})
  @PreAuthorize("@securityService.authorize('DATA', 'READ', #region)")
  public ResponseEntity<?> keys(@PathVariable("region") String region) {
    logger.debug("Reading all Keys in Region ({})...", region);

    region = decode(region);

    Object[] keys = getKeys(region, null);

    String listKeysAsJson = JSONUtils.formulateJsonForListKeys(keys, "keys");
    final HttpHeaders headers = new HttpHeaders();
    headers.setLocation(toUri(region, "keys"));
    return new ResponseEntity<>(listKeysAsJson, headers, HttpStatus.OK);
  }

  /**
   * Delete data for single key or specific keys in region
   *
   * @param region gemfire region
   * @param keys for which data is requested
   * @return JSON document containing result
   */
  @RequestMapping(method = RequestMethod.DELETE, value = "/{region}/{keys}",
      produces = {MediaType.APPLICATION_JSON_VALUE})
  @ApiOperation(value = "delete data for key(s)",
      notes = "Delete data for single key or specific keys in region")
  @ApiResponses({@ApiResponse(code = 200, message = "OK"),
      @ApiResponse(code = 401, message = "Invalid Username or Password."),
      @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
      @ApiResponse(code = 404, message = "Region or key(s) does not exist"),
      @ApiResponse(code = 500, message = "GemFire throws an error or exception")})
  @PreAuthorize("@securityService.authorize('WRITE', #region, #keys)")
  public ResponseEntity<?> delete(@PathVariable("region") String region,
      @PathVariable("keys") final String[] keys) {
    logger.debug("Delete data for key {} on region {}", ArrayUtils.toString((Object[]) keys),
        region);

    region = decode(region);

    deleteValues(region, (Object[]) keys);
    return new ResponseEntity<>(HttpStatus.OK);
  }

  /**
   * Delete all data in region
   *
   * @param region gemfire region
   * @return JSON document containing result
   */
  @RequestMapping(method = RequestMethod.DELETE, value = "/{region}")
  @ApiOperation(value = "delete all data", notes = "Delete all data in the region")
  @ApiResponses({@ApiResponse(code = 200, message = "OK"),
      @ApiResponse(code = 401, message = "Invalid Username or Password."),
      @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
      @ApiResponse(code = 404, message = "Region does not exist"),
      @ApiResponse(code = 500, message = "if GemFire throws an error or exception")})
  @PreAuthorize("@securityService.authorize('DATA', 'WRITE', #region)")
  public ResponseEntity<?> delete(@PathVariable("region") String region) {
    logger.debug("Deleting all data in Region ({})...", region);

    region = decode(region);

    deleteValues(region);
    return new ResponseEntity<>(HttpStatus.OK);
  }

  /**
   * Ping is not secured so that it may not be used to determine a valid username/password
   */
  @RequestMapping(method = {RequestMethod.GET, RequestMethod.HEAD}, value = "/ping")
  @ApiOperation(value = "Check Rest service status ",
      notes = "Check whether gemfire REST service is up and running!")
  @ApiResponses({@ApiResponse(code = 200, message = "OK"),
      @ApiResponse(code = 500, message = "if GemFire throws an error or exception")})
  public ResponseEntity<?> ping() {
    return new ResponseEntity<>(HttpStatus.OK);
  }

  @RequestMapping(method = {RequestMethod.GET}, value = "/servers",
      produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
  @ApiOperation(value = "fetch all REST enabled servers in the DS",
      notes = "Find all gemfire node where developer REST service is up and running!")
  @ApiResponses({@ApiResponse(code = 200, message = "OK"),
      @ApiResponse(code = 401, message = "Invalid Username or Password."),
      @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
      @ApiResponse(code = 500, message = "if GemFire throws an error or exception")})
  @PreAuthorize("@securityService.authorize('CLUSTER', 'READ')")
  public ResponseEntity<?> servers() {
    logger.debug("Executing function to get REST enabled gemfire nodes in the DS!");

    Execution function;
    try {
      function = FunctionService.onMembers(getAllMembersInDS());
    } catch (FunctionException fe) {
      throw new GemfireRestException(
          "Distributed system does not contain any valid data node that can host REST service!",
          fe);
    }

    try {
      final ResultCollector<?, ?> results = function.withCollector(new RestServersResultCollector())
          .execute(FindRestEnabledServersFunction.FIND_REST_ENABLED_SERVERS_FUNCTION_ID);
      Object functionResult = results.getResult();

      if (functionResult instanceof List<?>) {
        final HttpHeaders headers = new HttpHeaders();
        headers.setLocation(toUri("servers"));
        String functionResultAsJson =
            JSONUtils.convertCollectionToJson((ArrayList<Object>) functionResult);
        return new ResponseEntity<>(functionResultAsJson, headers, HttpStatus.OK);
      } else {
        throw new GemfireRestException(
            "Function has returned results that could not be converted into Restful (JSON) format!");
      }

    } catch (ClassCastException cce) {
      throw new GemfireRestException("Key is of an inappropriate type for this region!", cce);
    } catch (NullPointerException npe) {
      throw new GemfireRestException(
          "Specified key is null and this region does not permit null keys!", npe);
    } catch (LowMemoryException lme) {
      throw new GemfireRestException("Server has encountered low memory condition!", lme);
    } catch (IllegalArgumentException ie) {
      throw new GemfireRestException("Input parameter is null! ", ie);
    } catch (FunctionException fe) {
      throw new GemfireRestException("Server has encountered error while executing the function!",
          fe);
    }
  }
}
