/*
 * 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.List;
import java.util.Map;

import io.swagger.annotations.Api;
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.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.rest.internal.web.controllers.support.JSONTypes;
import org.apache.geode.rest.internal.web.controllers.support.RegionData;
import org.apache.geode.rest.internal.web.controllers.support.RegionEntryData;
import org.apache.geode.rest.internal.web.exception.ResourceNotFoundException;
import org.apache.geode.rest.internal.web.util.ArrayUtils;

/**
 * The PdxBasedCrudController class serving REST Requests related to the REST CRUD operation on
 * region
 *
 * @see org.springframework.stereotype.Controller
 * @since GemFire 8.0
 */
@Controller("pdxCrudController")
@Api(value = "region", description = "region CRUD operations", tags = "region")
@RequestMapping(PdxBasedCrudController.REST_API_VERSION)
@SuppressWarnings("unused")
public class PdxBasedCrudController extends CommonCrudController {

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

  static final String REST_API_VERSION = "/v1";

  private static final String DEFAULT_GETALL_RESULT_LIMIT = "50";

  @Override
  protected String getRestApiVersion() {
    return REST_API_VERSION;
  }

  /**
   * Creating entry into the region
   *
   * @param region region name where data will be created
   * @param key gemfire region key
   * @param json JSON document that is stored against the key
   * @return JSON document
   */
  @RequestMapping(method = RequestMethod.POST, value = "/{region}",
      consumes = MediaType.APPLICATION_JSON_VALUE, produces = {MediaType.APPLICATION_JSON_VALUE})
  @ApiOperation(value = "create entry", notes = "Create (put-if-absent) data in region")
  @ApiResponses({@ApiResponse(code = 201, message = "Created."),
      @ApiResponse(code = 400,
          message = "Data specified (JSON doc) in the request body is invalid."),
      @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 = 409, message = "Key already exist in region."),
      @ApiResponse(code = 500, message = "GemFire throws an error or exception.")})
  @PreAuthorize("@securityService.authorize('DATA', 'WRITE', #region)")
  public ResponseEntity<?> create(@PathVariable("region") String region,
      @RequestParam(value = "key", required = false) String key, @RequestBody final String json) {
    key = generateKey(key);

    logger.debug(
        "Posting (creating/putIfAbsent) JSON document ({}) to Region ({}) with Key ({})...", json,
        region, key);

    region = decode(region);
    Object existingPdxObj = null;

    // Check whether the user has supplied single JSON doc or Array of JSON docs
    final JSONTypes jsonType = validateJsonAndFindType(json);
    if (JSONTypes.JSON_ARRAY.equals(jsonType)) {
      existingPdxObj = postValue(region, key, convertJsonArrayIntoPdxCollection(json));
    } else {
      existingPdxObj = postValue(region, key, convert(json));
    }

    final HttpHeaders headers = new HttpHeaders();
    headers.setLocation(toUri(region, key));

    if (existingPdxObj != null) {
      final RegionEntryData<Object> data = new RegionEntryData<>(region);
      data.add(existingPdxObj);
      headers.setContentType(MediaType.APPLICATION_JSON);
      return new ResponseEntity<RegionEntryData<?>>(data, headers, HttpStatus.CONFLICT);
    } else {
      return new ResponseEntity<String>(headers, HttpStatus.CREATED);
    }
  }

  /**
   * Read all or fixed number of data in a given Region
   *
   * @param region gemfire region name
   * @param limit total number of entries requested
   * @return JSON document
   */
  @RequestMapping(method = RequestMethod.GET, value = "/{region}",
      produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
  @ApiOperation(value = "read all data for region",
      notes = "Read all data for region. Use limit param to get fixed or limited number of entries.")
  @ApiResponses({@ApiResponse(code = 200, message = "OK."),
      @ApiResponse(code = 400, message = "Bad request."),
      @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<?> read(@PathVariable("region") String region,
      @RequestParam(value = "limit",
          defaultValue = DEFAULT_GETALL_RESULT_LIMIT) final String limit) {
    logger.debug("Reading all data in Region ({})...", region);

    region = decode(region);

    Map<Object, Object> valueObjs = null;
    final RegionData<Object> data = new RegionData<>(region);

    final HttpHeaders headers = new HttpHeaders();
    String keyList = null;
    int regionSize = getRegion(region).size();
    List<Object> keys = new ArrayList<>(regionSize);
    List<Object> values = new ArrayList<>(regionSize);

    for (Map.Entry<Object, Object> entry : getValues(region).entrySet()) {
      Object value = entry.getValue();
      if (value != null) {
        keys.add(entry.getKey());
        values.add(value);
      }
    }

    if ("ALL".equalsIgnoreCase(limit)) {
      data.add(values);
      keyList = StringUtils.collectionToDelimitedString(keys, ",");
    } else {
      try {
        int maxLimit = Integer.valueOf(limit);
        if (maxLimit < 0) {
          String errorMessage =
              String.format("Negative limit param (%1$s) is not valid!", maxLimit);
          return new ResponseEntity<>(convertErrorAsJson(errorMessage), HttpStatus.BAD_REQUEST);
        }

        int mapSize = keys.size();
        if (maxLimit > mapSize) {
          maxLimit = mapSize;
        }
        data.add(values.subList(0, maxLimit));

        keyList = StringUtils.collectionToDelimitedString(keys.subList(0, maxLimit), ",");

      } catch (NumberFormatException e) {
        // limit param is not specified in proper format. set the HTTPHeader
        // for BAD_REQUEST
        String errorMessage = String.format("limit param (%1$s) is not valid!", limit);
        return new ResponseEntity<>(convertErrorAsJson(errorMessage), HttpStatus.BAD_REQUEST);
      }
    }

    headers.set("Content-Location", toUri(region, keyList).toASCIIString());
    return new ResponseEntity<RegionData<?>>(data, headers, HttpStatus.OK);
  }

  /**
   * Reading data for set of keys
   *
   * @param region gemfire region name
   * @param keys string containing comma separated keys
   * @return JSON document
   */
  @RequestMapping(method = RequestMethod.GET, value = "/{region}/{keys}",
      produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
  @ApiOperation(value = "read data for specific keys",
      notes = "Read data for specific set of keys in region.")
  @ApiResponses({@ApiResponse(code = 200, message = "OK."),
      @ApiResponse(code = 400, message = "Bad Request."),
      @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('READ', #region, #keys)")
  public ResponseEntity<?> read(@PathVariable("region") String region,
      @PathVariable("keys") final String[] keys,
      @RequestParam(value = "ignoreMissingKey", required = false) final String ignoreMissingKey) {
    logger.debug("Reading data for keys ({}) in Region ({})", ArrayUtils.toString(keys), region);

    final HttpHeaders headers = new HttpHeaders();
    region = decode(region);

    if (keys.length == 1) {
      /* GET op on single key */
      Object value = getValue(region, keys[0]);
      // if region.get(K) return null (i.e INVLD or TOMBSTONE case) We consider 404, NOT Found case
      if (value == null) {
        throw new ResourceNotFoundException(String
            .format("Key (%1$s) does not exist for region (%2$s) in cache!", keys[0], region));
      }

      final RegionEntryData<Object> data = new RegionEntryData<>(region);
      headers.set("Content-Location", toUri(region, keys[0]).toASCIIString());
      data.add(value);
      return new ResponseEntity<RegionData<?>>(data, headers, HttpStatus.OK);

    } else {
      // fail fast for the case where ignoreMissingKey param is not specified correctly.
      if (ignoreMissingKey != null && !(ignoreMissingKey.equalsIgnoreCase("true")
          || ignoreMissingKey.equalsIgnoreCase("false"))) {
        String errorMessage = String.format(
            "ignoreMissingKey param (%1$s) is not valid. valid usage is ignoreMissingKey=true!",
            ignoreMissingKey);
        return new ResponseEntity<>(convertErrorAsJson(errorMessage), HttpStatus.BAD_REQUEST);
      }

      if (!("true".equalsIgnoreCase(ignoreMissingKey))) {
        List<String> unknownKeys = checkForMultipleKeysExist(region, keys);
        if (unknownKeys.size() > 0) {
          String unknownKeysAsStr = StringUtils.collectionToDelimitedString(unknownKeys, ",");
          String erroString = String.format("Requested keys (%1$s) not exist in region (%2$s)",
              StringUtils.collectionToDelimitedString(unknownKeys, ","), region);
          return new ResponseEntity<>(convertErrorAsJson(erroString), headers,
              HttpStatus.BAD_REQUEST);
        }
      }

      final Map<Object, Object> valueObjs = getValues(region, keys);

      // Do we need to remove null values from Map..?
      // To Remove null value entries from map.
      // valueObjs.values().removeAll(Collections.singleton(null));

      // currently we are not removing keys having value null from the result.
      String keyList = StringUtils.collectionToDelimitedString(valueObjs.keySet(), ",");
      headers.set("Content-Location", toUri(region, keyList).toASCIIString());
      final RegionData<Object> data = new RegionData<>(region);
      data.add(valueObjs.values());
      return new ResponseEntity<RegionData<?>>(data, headers, HttpStatus.OK);
    }
  }

  /**
   * Update data for a key or set of keys
   *
   * @param region gemfire data region
   * @param keys keys for which update operation is requested
   * @param opValue type of update (put, replace, cas etc)
   * @param json new data for the key(s)
   * @return JSON document
   */
  @RequestMapping(method = RequestMethod.PUT, value = "/{region}/{keys}",
      consumes = {MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE})
  @ApiOperation(value = "update data for key",
      notes = "Update or insert (put) data for key in region."
          + "op=REPLACE, update (replace) data with key if and only if the key exists in region"
          + "op=CAS update (compare-and-set) value having key with a new value if and only if the \"@old\" value sent matches the current value for the key in region")
  @ApiResponses({@ApiResponse(code = 200, message = "OK."),
      @ApiResponse(code = 400, message = "Bad Request."),
      @ApiResponse(code = 401, message = "Invalid Username or Password."),
      @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
      @ApiResponse(code = 404,
          message = "Region does not exist or if key is not mapped to some value for REPLACE or CAS."),
      @ApiResponse(code = 409,
          message = "For CAS, @old value does not match to the current value in region"),
      @ApiResponse(code = 500, message = "GemFire throws an error or exception.")})
  @PreAuthorize("@securityService.authorize('WRITE', #region, #keys)")
  public ResponseEntity<?> update(@PathVariable("region") String region,
      @PathVariable("keys") final String[] keys,
      @RequestParam(value = "op", defaultValue = "PUT") final String opValue,
      @RequestBody final String json) {
    logger.debug("updating key(s) for region ({}) ", region);

    region = decode(region);

    if (keys.length > 1) {
      // putAll case
      return updateMultipleKeys(region, keys, json);
    } else {
      // put case
      return updateSingleKey(region, keys[0], json, opValue);
    }
  }

  @RequestMapping(method = RequestMethod.HEAD, value = "/{region}",
      produces = MediaType.APPLICATION_JSON_VALUE)
  @ApiOperation(value = "Get total number of entries",
      notes = "Get total number of entries into the specified region")
  @ApiResponses({@ApiResponse(code = 200, message = "OK."),
      @ApiResponse(code = 400, message = "Bad request."),
      @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<?> size(@PathVariable("region") String region) {
    logger.debug("Determining the number of entries in Region ({})...", region);

    region = decode(region);

    final HttpHeaders headers = new HttpHeaders();

    headers.set("Resource-Count", String.valueOf(getRegion(region).size()));
    return new ResponseEntity<RegionData<?>>(headers, HttpStatus.OK);
  }

}
