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

import static org.apache.commons.io.IOUtils.toInputStream;
import static org.apache.geode.management.internal.web.util.UriUtils.decode;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.Set;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
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.multipart.MultipartFile;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.internal.GemFireVersion;
import org.apache.geode.internal.util.IOUtils;
import org.apache.geode.management.cli.Result;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.result.model.ResultModel;
import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
import org.apache.geode.management.internal.web.domain.QueryParameterSource;
import org.apache.geode.util.internal.GeodeConverter;

/**
 * The ShellCommandsController class implements GemFire REST API calls for Gfsh Shell Commands.
 *
 * @see org.springframework.stereotype.Controller
 * @see org.springframework.web.bind.annotation.RequestBody
 * @see org.springframework.web.bind.annotation.RequestMapping
 * @see org.springframework.web.bind.annotation.RequestMethod
 * @see org.springframework.web.bind.annotation.RequestParam
 * @see org.springframework.web.bind.annotation.ResponseBody
 * @since GemFire 8.0
 */
@Controller("shellController")
@RequestMapping(AbstractCommandsController.REST_API_VERSION)
@SuppressWarnings("unused")
public class ShellCommandsController extends AbstractCommandsController {

  @Immutable
  private static final MultipartFile[] DEFAULT_MULTIPART_FILE = null;

  private static final String DEFAULT_INDEX_TYPE = "range";

  @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, value = "/management/commands")
  public ResponseEntity<InputStreamResource> command(@RequestParam(value = "cmd") String command,
      @RequestParam(value = "resources", required = false) MultipartFile[] fileResource)
      throws IOException {
    String result = processCommand(decode(command), getEnvironment(), fileResource);
    return getResponse(result);
  }

  @RequestMapping(method = RequestMethod.POST, value = "/indexes")
  public ResponseEntity<?> createIndex(@RequestParam(CliStrings.CREATE_INDEX__NAME) String name,
      @RequestParam(CliStrings.CREATE_INDEX__EXPRESSION) String expression,
      @RequestParam(CliStrings.CREATE_INDEX__REGION) String region,
      @RequestParam(value = CliStrings.CREATE_INDEX__TYPE,
          defaultValue = DEFAULT_INDEX_TYPE) String type)
      throws IOException {

    CommandStringBuilder command = new CommandStringBuilder(CliStrings.CREATE_INDEX);

    command.addOption(CliStrings.CREATE_INDEX__NAME, name);
    command.addOption(CliStrings.CREATE_INDEX__EXPRESSION, expression);
    command.addOption(CliStrings.CREATE_INDEX__REGION, region);
    command.addOption(CliStrings.CREATE_INDEX__TYPE, type);

    return command(command.toString(), DEFAULT_MULTIPART_FILE);
  }

  @RequestMapping(method = RequestMethod.POST, value = "/regions")
  public ResponseEntity<?> createRegion(
      @RequestParam(CliStrings.CREATE_REGION__REGION) String namePath,
      @RequestParam(value = CliStrings.CREATE_REGION__SKIPIFEXISTS,
          defaultValue = "false") Boolean skipIfExists,
      @RequestParam(value = CliStrings.CREATE_REGION__REGIONSHORTCUT,
          defaultValue = "PARTITION") RegionShortcut type)
      throws IOException {

    CommandStringBuilder command = new CommandStringBuilder(CliStrings.CREATE_REGION);

    command.addOption(CliStrings.CREATE_REGION__REGION, namePath);
    command.addOption(CliStrings.CREATE_REGION__REGIONSHORTCUT, type.name());

    Optional.ofNullable(skipIfExists)
        .ifPresent(it -> command.addOption(CliStrings.CREATE_REGION__SKIPIFEXISTS, it.toString()));

    return command(command.toString(), DEFAULT_MULTIPART_FILE);
  }

  @RequestMapping(method = RequestMethod.GET, value = "/mbean/attribute")
  public ResponseEntity<?> getAttribute(@RequestParam("resourceName") final String resourceName,
      @RequestParam("attributeName") final String attributeName)
      throws AttributeNotFoundException, MBeanException, ReflectionException,
      InstanceNotFoundException, IOException, MalformedObjectNameException {
    // Exceptions are caught by the @ExceptionHandler AbstractCommandsController.handleAppException
    MBeanServer mBeanServer = getMBeanServer();
    ObjectName objectName = ObjectName.getInstance(decode(resourceName));
    final Object attributeValue = mBeanServer.getAttribute(objectName, decode(attributeName));
    byte[] serializedResult = IOUtils.serializeObject(attributeValue);
    return new ResponseEntity<>(serializedResult, HttpStatus.OK);
  }

  @RequestMapping(method = RequestMethod.POST, value = "/mbean/operation")
  public ResponseEntity<?> invoke(@RequestParam("resourceName") final String resourceName,
      @RequestParam("operationName") final String operationName,
      @RequestParam(value = "signature", required = false) String[] signature,
      @RequestParam(value = "parameters", required = false) Object[] parameters)
      throws MalformedObjectNameException, MBeanException, InstanceNotFoundException,
      ReflectionException, IOException {
    // Exceptions are caught by the @ExceptionHandler AbstractCommandsController.handleAppException
    signature = (signature != null ? signature : ArrayUtils.EMPTY_STRING_ARRAY);
    parameters = (parameters != null ? parameters : ArrayUtils.EMPTY_OBJECT_ARRAY);
    MBeanServer mBeanServer = getMBeanServer();
    ObjectName objectName = ObjectName.getInstance(decode(resourceName));
    // GEODE-6182
    for (int i = 0; i < signature.length; i++) {
      parameters[i] = GeodeConverter.convertToActualType(parameters[i].toString(), signature[i]);
    }

    final Object result =
        mBeanServer.invoke(objectName, decode(operationName), parameters, signature);
    byte[] serializedResult = IOUtils.serializeObject(result);
    return new ResponseEntity<>(serializedResult, HttpStatus.OK);
  }

  @RequestMapping(method = RequestMethod.POST, value = "/mbean/query")
  public ResponseEntity<?> queryNames(@RequestBody final QueryParameterSource query)
      throws IOException {
    // Exceptions are caught by the @ExceptionHandler AbstractCommandsController.handleAppException
    final Set<ObjectName> objectNames =
        getMBeanServer().queryNames(query.getObjectName(), query.getQueryExpression());
    return new ResponseEntity<>(IOUtils.serializeObject(objectNames), HttpStatus.OK);
  }

  @RequestMapping(method = {RequestMethod.GET, RequestMethod.HEAD}, value = "/ping")
  public ResponseEntity<String> ping() {
    return new ResponseEntity<>("pong", HttpStatus.OK);
  }

  @RequestMapping(method = RequestMethod.GET, value = "/version")
  @ResponseBody
  public String version() {
    return GemFireVersion.getProductName().concat("/").concat(GemFireVersion.getGemFireVersion());
  }

  @RequestMapping(method = RequestMethod.GET, value = "/version/full")
  @ResponseBody
  public String fullVersion() {
    return GemFireVersion.asString();
  }

  @RequestMapping(method = RequestMethod.GET, value = "/version/release")
  @ResponseBody
  public String releaseVersion() {
    return GemFireVersion.getGemFireVersion();
  }


  private ResponseEntity<InputStreamResource> getResponse(String result) {
    ResultModel commandResult = ResultModel.fromJson(result);
    if (commandResult.getStatus().equals(Result.Status.OK)
        && commandResult.getFileToDownload() != null) {
      return getFileDownloadResponse(commandResult);
    } else {
      return getJsonResponse(result);
    }
  }

  private ResponseEntity<InputStreamResource> getJsonResponse(String result) {
    HttpHeaders respHeaders = new HttpHeaders();
    try {
      InputStreamResource isr = new InputStreamResource(toInputStream(result, "UTF-8"));
      respHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
      return new ResponseEntity<>(isr, respHeaders, HttpStatus.OK);
    } catch (Exception e) {
      throw new RuntimeException("IO Error writing file to output stream", e);
    }
  }

  private ResponseEntity<InputStreamResource> getFileDownloadResponse(ResultModel commandResult) {
    HttpHeaders respHeaders = new HttpHeaders();
    Path filePath = commandResult.getFileToDownload();
    try {
      InputStreamResource isr = new InputStreamResource(new FileInputStream(filePath.toFile()));
      respHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
      return new ResponseEntity<>(isr, respHeaders, HttpStatus.OK);
    } catch (Exception e) {
      throw new RuntimeException("IO Error writing file to output stream", e);
    } finally {
      FileUtils.deleteQuietly(filePath.toFile());
    }
  }
}
