/*
 * 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.concurrent.ConcurrentHashMap;

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.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.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import org.apache.geode.cache.Region;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.Query;
import org.apache.geode.cache.query.QueryExecutionLowMemoryException;
import org.apache.geode.cache.query.QueryExecutionTimeoutException;
import org.apache.geode.cache.query.QueryInvalidException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.query.internal.DefaultQuery;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.rest.internal.web.exception.GemfireRestException;
import org.apache.geode.rest.internal.web.exception.ResourceNotFoundException;
import org.apache.geode.rest.internal.web.util.JSONUtils;
import org.apache.geode.rest.internal.web.util.ValidationUtils;

/**
 * The QueryingController class serves all HTTP REST requests related to the gemfire querying
 *
 * @see org.springframework.stereotype.Controller
 * @since GemFire 8.0
 */
@Controller("queryController")
@Api(value = "queries", description = "Rest api for geode query execution",
    produces = MediaType.APPLICATION_JSON_VALUE, tags = "queries")
@RequestMapping(QueryAccessController.REST_API_VERSION + "/queries")
@SuppressWarnings("unused")
public class QueryAccessController extends AbstractBaseController {

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

  static final String PARAMETERIZED_QUERIES_REGION = "__ParameterizedQueries__";

  private final ConcurrentHashMap<String, DefaultQuery> compiledQueries = new ConcurrentHashMap<>();

  // Constant String value indicating the version of the REST API.
  static final String REST_API_VERSION = "/v1";

  /**
   * Gets the version of the REST API implemented by this @Controller.
   *
   * @return a String indicating the REST API version.
   */
  @Override
  protected String getRestApiVersion() {
    return REST_API_VERSION;
  }

  /**
   * list all parametrized Queries created in a Gemfire data node
   *
   * @return result as a JSON document.
   */
  @RequestMapping(method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
  @ApiOperation(value = "list all parametrized queries",
      notes = "List all parametrized queries by id/name")
  @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")})
  @ResponseBody
  @ResponseStatus(HttpStatus.OK)
  @PreAuthorize("@securityService.authorize('DATA', 'READ')")
  public ResponseEntity<?> list() {
    logger.debug("Listing all parametrized Queries in GemFire...");

    final Region<String, String> parametrizedQueryRegion =
        getQueryStore(PARAMETERIZED_QUERIES_REGION);

    String queryListAsJson = JSONUtils.formulateJsonForListQueriesCall(parametrizedQueryRegion);
    final HttpHeaders headers = new HttpHeaders();
    headers.setLocation(toUri("queries"));
    return new ResponseEntity<>(queryListAsJson, headers, HttpStatus.OK);
  }

  /**
   * Create a named, parametrized Query
   *
   * @param queryId uniquely identify the query
   * @param oqlInUrl OQL query string specified in a request URL
   * @param oqlInBody OQL query string specified in a request body
   * @return result as a JSON document.
   */
  @RequestMapping(method = RequestMethod.POST)
  @ApiOperation(value = "create a parametrized Query",
      notes = "Prepare the specified parametrized query and assign the corresponding ID for lookup")
  @ApiResponses({@ApiResponse(code = 201, message = "Successfully created."),
      @ApiResponse(code = 401, message = "Invalid Username or Password."),
      @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
      @ApiResponse(code = 409, message = "QueryId already assigned to other query."),
      @ApiResponse(code = 500, message = "GemFire throws an error or exception.")})
  @PreAuthorize("@securityService.authorize('DATA', 'READ')")
  public ResponseEntity<?> create(@RequestParam("id") final String queryId,
      @RequestParam(value = "q", required = false) String oqlInUrl,
      @RequestBody(required = false) final String oqlInBody) {
    final String oqlStatement = validateQuery(oqlInUrl, oqlInBody);
    logger.debug("Creating a named, parametrized Query ({}) with ID ({})...", oqlStatement,
        queryId);


    // store the compiled OQL statement with 'queryId' as the Key into the hidden,
    // Parametrized Queries Region...
    final String existingOql =
        createNamedQuery(PARAMETERIZED_QUERIES_REGION, queryId, oqlStatement);

    final HttpHeaders headers = new HttpHeaders();
    headers.setLocation(toUri("queries", queryId));

    if (existingOql != null) {
      headers.setContentType(MediaType.APPLICATION_JSON);
      return new ResponseEntity<>(JSONUtils.formulateJsonForExistingQuery(queryId, existingOql),
          headers, HttpStatus.CONFLICT);
    } else {
      return new ResponseEntity<String>(headers, HttpStatus.CREATED);
    }
  }

  /**
   * Run an adhoc Query specified in a query string
   *
   * @param oql OQL query string to be executed
   * @return query result as a JSON document
   */
  @RequestMapping(method = RequestMethod.GET, value = "/adhoc",
      produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
  @ApiOperation(value = "run an adhoc query",
      notes = "Run an unnamed (unidentified), ad-hoc query passed as a URL parameter")
  @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")})
  @ResponseBody
  @ResponseStatus(HttpStatus.OK)
  @PreAuthorize("@securityService.authorize('DATA', 'READ')")
  public ResponseEntity<String> runAdhocQuery(@RequestParam("q") String oql) {
    logger.debug("Running an adhoc Query ({})...", oql);

    oql = decode(oql);
    final Query query = getQueryService().newQuery(oql);

    // NOTE Query.execute throws many checked Exceptions; let the BaseControllerAdvice Exception
    // handlers catch
    // and handle the Exceptions appropriately (500 Server Error)!
    try {
      Object queryResult = query.execute();
      return processQueryResponse(query, null, queryResult);
    } catch (FunctionDomainException fde) {
      throw new GemfireRestException(
          "A function was applied to a parameter that is improper for that function!", fde);
    } catch (TypeMismatchException tme) {
      throw new GemfireRestException("Bind parameter is not of the expected type!", tme);
    } catch (NameResolutionException nre) {
      throw new GemfireRestException("Name in the query cannot be resolved!", nre);
    } catch (IllegalArgumentException iae) {
      throw new GemfireRestException(
          " The number of bound parameters does not match the number of placeholders!", iae);
    } catch (IllegalStateException ise) {
      throw new GemfireRestException("Query is not permitted on this type of region!", ise);
    } catch (QueryExecutionTimeoutException qete) {
      throw new GemfireRestException(
          "Query execution time is exceeded max query execution time (gemfire.Cache.MAX_QUERY_EXECUTION_TIME) configured! ",
          qete);
    } catch (QueryInvocationTargetException qite) {
      throw new GemfireRestException(
          "Data referenced in from clause is not available for querying!", qite);
    } catch (QueryExecutionLowMemoryException qelme) {
      throw new GemfireRestException(
          "Query execution gets canceled due to low memory conditions and the resource manager critical heap percentage has been set!",
          qelme);
    } catch (Exception ex) {
      throw new GemfireRestException(ex.getMessage(), ex);
    }
  }

  /**
   * Run named parametrized Query with ID
   *
   * @param queryId id of the OQL string
   * @param arguments query bind params required while executing query
   * @return query result as a JSON document
   */
  @RequestMapping(method = RequestMethod.POST, value = "/{query}",
      produces = {MediaType.APPLICATION_JSON_VALUE})
  @ApiOperation(value = "run parametrized query",
      notes = "run the specified named query passing in scalar values for query parameters in the GemFire cluster")
  @ApiResponses({@ApiResponse(code = 200, message = "Query successfully executed."),
      @ApiResponse(code = 401, message = "Invalid Username or Password."),
      @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
      @ApiResponse(code = 400,
          message = "Query bind params specified as JSON document in the request body is invalid"),
      @ApiResponse(code = 500, message = "GemFire throws an error or exception")})
  @ResponseBody
  @ResponseStatus(HttpStatus.OK)
  @PreAuthorize("@securityService.authorize('DATA', 'READ')")
  public ResponseEntity<String> runNamedQuery(@PathVariable("query") String queryId,
      @RequestBody String arguments) {
    logger.debug("Running named Query with ID ({})...", queryId);

    queryId = decode(queryId);

    if (arguments != null) {
      // Its a compiled query.

      // Convert arguments into Object[]
      Object args[] = jsonToObjectArray(arguments);

      Query compiledQuery = compiledQueries.get(queryId);
      if (compiledQuery == null) {
        // This is first time the query is seen by this server.
        final String oql = getQueryStore(PARAMETERIZED_QUERIES_REGION).get(queryId);

        ValidationUtils.returnValueThrowOnNull(oql, new ResourceNotFoundException(
            String.format("No Query with ID (%1$s) was found!", queryId)));
        try {
          compiledQuery = getQueryService().newQuery(oql);
        } catch (QueryInvalidException qie) {
          throw new GemfireRestException("Syntax of the OQL queryString is invalid!", qie);
        }
        compiledQueries.putIfAbsent(queryId, (DefaultQuery) compiledQuery);
      }
      // NOTE Query.execute throws many checked Exceptions; let the BaseControllerAdvice Exception
      // handlers catch
      // and handle the Exceptions appropriately (500 Server Error)!
      try {
        Object queryResult = compiledQuery.execute(args);
        return processQueryResponse(compiledQuery, args, queryResult);
      } catch (FunctionDomainException fde) {
        throw new GemfireRestException(
            "A function was applied to a parameter that is improper for that function!", fde);
      } catch (TypeMismatchException tme) {
        throw new GemfireRestException("Bind parameter is not of the expected type!", tme);
      } catch (NameResolutionException nre) {
        throw new GemfireRestException("Name in the query cannot be resolved!", nre);
      } catch (IllegalArgumentException iae) {
        throw new GemfireRestException(
            " The number of bound parameters does not match the number of placeholders!", iae);
      } catch (IllegalStateException ise) {
        throw new GemfireRestException("Query is not permitted on this type of region!", ise);
      } catch (QueryExecutionTimeoutException qete) {
        throw new GemfireRestException(
            "Query execution time is exceeded  max query execution time (gemfire.Cache.MAX_QUERY_EXECUTION_TIME) configured!",
            qete);
      } catch (QueryInvocationTargetException qite) {
        throw new GemfireRestException(
            "Data referenced in from clause is not available for querying!", qite);
      } catch (QueryExecutionLowMemoryException qelme) {
        throw new GemfireRestException(
            "Query gets canceled due to low memory conditions and the resource manager critical heap percentage has been set!",
            qelme);
      } catch (Exception e) {
        throw new GemfireRestException("Error encountered while executing named query!", e);
      }
    } else {
      throw new GemfireRestException(
          " Bind params either not specified or not processed properly by the server!");
    }
  }

  /**
   * Update named, parametrized Query
   *
   * @param queryId uniquely identify the query
   * @param oqlInUrl OQL query string specified in a request URL
   * @param oqlInBody OQL query string specified in a request body
   */
  @RequestMapping(method = RequestMethod.PUT, value = "/{query}")
  @ApiOperation(value = "update parametrized query",
      notes = "Update named, parametrized query by ID")
  @ApiResponses({@ApiResponse(code = 200, message = "Updated successfully."),
      @ApiResponse(code = 401, message = "Invalid Username or Password."),
      @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
      @ApiResponse(code = 404, message = "queryId does not exist."),
      @ApiResponse(code = 500, message = "GemFire throws an error or exception.")})
  @PreAuthorize("@securityService.authorize('DATA', 'READ')")
  public ResponseEntity<?> update(@PathVariable("query") final String queryId,
      @RequestParam(value = "q", required = false) String oqlInUrl,
      @RequestBody(required = false) final String oqlInBody) {
    final String oqlStatement = validateQuery(oqlInUrl, oqlInBody);

    logger.debug("Updating a named, parametrized Query ({}) with ID ({})...", oqlStatement,
        queryId);

    // update the OQL statement with 'queryId' as the Key into the hidden, Parametrized Queries
    // Region...
    checkForQueryIdExist(PARAMETERIZED_QUERIES_REGION, queryId);
    updateNamedQuery(PARAMETERIZED_QUERIES_REGION, queryId, oqlStatement);
    compiledQueries.remove(queryId);

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

  /**
   * Delete named, parametrized Query
   *
   * @param queryId uniquely identify the query to be deleted
   */
  @RequestMapping(method = RequestMethod.DELETE, value = "/{query}")
  @ApiOperation(value = "delete parametrized query",
      notes = "delete named, parametrized query by ID")
  @ApiResponses({@ApiResponse(code = 200, message = "Deleted successfully."),
      @ApiResponse(code = 401, message = "Invalid Username or Password."),
      @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
      @ApiResponse(code = 404, message = "queryId does not exist."),
      @ApiResponse(code = 500, message = "GemFire throws an error or exception")})
  @PreAuthorize("@securityService.authorize('DATA', 'WRITE')")
  public ResponseEntity<?> delete(@PathVariable("query") final String queryId) {
    logger.debug("Deleting a named, parametrized Query with ID ({}).", queryId);

    // delete the OQL statement with 'queryId' as the Key into the hidden,
    // ParameterizedQueries Region...
    deleteNamedQuery(PARAMETERIZED_QUERIES_REGION, queryId);
    compiledQueries.remove(queryId);
    return new ResponseEntity<>(HttpStatus.OK);
  }

}
