/**
 * 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.
 */

#ifndef __YARN_POSIX_CONTAINER_EXECUTOR_DOCKER_UTIL_H__
#define __YARN_POSIX_CONTAINER_EXECUTOR_DOCKER_UTIL_H__

#include "configuration.h"

#define CONTAINER_EXECUTOR_CFG_DOCKER_SECTION "docker"
#define DOCKER_BINARY_KEY "docker.binary"
#define DOCKER_COMMAND_FILE_SECTION "docker-command-execution"
#define DOCKER_INSPECT_COMMAND "inspect"
#define DOCKER_LOAD_COMMAND "load"
#define DOCKER_PULL_COMMAND "pull"
#define DOCKER_RM_COMMAND "rm"
#define DOCKER_RUN_COMMAND "run"
#define DOCKER_STOP_COMMAND "stop"
#define DOCKER_VOLUME_COMMAND "volume"


enum docker_error_codes {
    INVALID_COMMAND_FILE = 1,
    INCORRECT_COMMAND,
    BUFFER_TOO_SMALL,
    INVALID_DOCKER_CONTAINER_NAME,
    INVALID_DOCKER_IMAGE_NAME,
    INVALID_DOCKER_USER_NAME,
    INVALID_DOCKER_INSPECT_FORMAT,
    UNKNOWN_DOCKER_COMMAND,
    INVALID_DOCKER_NETWORK,
    INVALID_DOCKER_CAPABILITY,
    PRIVILEGED_CONTAINERS_DISABLED,
    INVALID_DOCKER_MOUNT,
    INVALID_DOCKER_RO_MOUNT,
    INVALID_DOCKER_RW_MOUNT,
    MOUNT_ACCESS_ERROR,
    INVALID_DOCKER_DEVICE,
    INVALID_DOCKER_STOP_COMMAND,
    INVALID_DOCKER_VOLUME_DRIVER,
    INVALID_DOCKER_VOLUME_NAME,
    INVALID_DOCKER_VOLUME_COMMAND
};

/**
 * Get the full path for the docker binary.
 * @param conf Configuration for the container-executor
 * @return String containing the docker binary to be freed by the user.
 */
char *get_docker_binary(const struct configuration *conf);

/**
 * Get the Docker command line string. The function will inspect the params file to determine the command to be run.
 * @param command_file File containing the params for the Docker command
 * @param conf Configuration struct containing the container-executor.cfg details
 * @param out Buffer to fill with the Docker command
 * @param outlen Size of the output buffer
 * @return Return code with 0 indicating success and non-zero codes indicating error
 */
int get_docker_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen);

/**
 * Get the Docker inspect command line string. The function will verify that the params file is meant for the
 * inspect command.
 * @param command_file File containing the params for the Docker inspect command
 * @param conf Configuration struct containing the container-executor.cfg details
 * @param out Buffer to fill with the inspect command
 * @param outlen Size of the output buffer
 * @return Return code with 0 indicating success and non-zero codes indicating error
 */
int get_docker_inspect_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen);

/**
 * Get the Docker load command line string. The function will verify that the params file is meant for the load command.
 * @param command_file File containing the params for the Docker load command
 * @param conf Configuration struct containing the container-executor.cfg details
 * @param out Buffer to fill with the load command
 * @param outlen Size of the output buffer
 * @return Return code with 0 indicating success and non-zero codes indicating error
 */
int get_docker_load_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen);

/**
 * Get the Docker pull command line string. The function will verify that the params file is meant for the pull command.
 * @param command_file File containing the params for the Docker pull command
 * @param conf Configuration struct containing the container-executor.cfg details
 * @param out Buffer to fill with the pull command
 * @param outlen Size of the output buffer
 * @return Return code with 0 indicating success and non-zero codes indicating error
 */
int get_docker_pull_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen);

/**
 * Get the Docker rm command line string. The function will verify that the params file is meant for the rm command.
 * @param command_file File containing the params for the Docker rm command
 * @param conf Configuration struct containing the container-executor.cfg details
 * @param out Buffer to fill with the rm command
 * @param outlen Size of the output buffer
 * @return Return code with 0 indicating success and non-zero codes indicating error
 */
int get_docker_rm_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen);

/**
 * Get the Docker run command line string. The function will verify that the params file is meant for the run command.
 * @param command_file File containing the params for the Docker run command
 * @param conf Configuration struct containing the container-executor.cfg details
 * @param out Buffer to fill with the run command
 * @param outlen Size of the output buffer
 * @return Return code with 0 indicating success and non-zero codes indicating error
 */
int get_docker_run_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen);

/**
 * Get the Docker stop command line string. The function will verify that the params file is meant for the stop command.
 * @param command_file File containing the params for the Docker stop command
 * @param conf Configuration struct containing the container-executor.cfg details
 * @param out Buffer to fill with the stop command
 * @param outlen Size of the output buffer
 * @return Return code with 0 indicating success and non-zero codes indicating error
 */
int get_docker_stop_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen);

/**
 * Get the Docker volume command line string. The function will verify that the
 * params file is meant for the volume command.
 * @param command_file File containing the params for the Docker volume command
 * @param conf Configuration struct containing the container-executor.cfg details
 * @param out Buffer to fill with the volume command
 * @param outlen Size of the output buffer
 * @return Return code with 0 indicating success and non-zero codes indicating error
 */
int get_docker_volume_command(const char *command_file, const struct configuration *conf, char *out,
                               const size_t outlen);

/**
 * Give an error message for the supplied error code
 * @param error_code the error code
 * @return const string containing the error message
 */
const char *get_docker_error_message(const int error_code);

/**
 * Determine if the docker module is enabled in the config.
 * @param conf Configuration structure
 * @return 1 if enabled, 0 otherwise
 */
int docker_module_enabled(const struct configuration *conf);

#endif
