package com.iqser.red.service.persistence.service.v1.api.external.resource;

import java.util.List;
import java.util.Set;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.iqser.red.service.persistence.service.v1.api.shared.model.RotatePagesRequest;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;

public interface FileManagementResource {

    String DELETE_PATH = ExternalApi.BASE_PATH + "/delete";
    String DOWNLOAD_ORIGINAL_PATH = ExternalApi.BASE_PATH + "/download/original";
    String DOWNLOAD_VIEWER_DOCUMENT_PATH = ExternalApi.BASE_PATH + "/download/viewer_doc";
    String ROTATION_PATH = ExternalApi.BASE_PATH + "/rotate";

    String DOSSIER_ID = "dossierId";
    String FILE_ID = "fileId";
    String FILE_IDS = "fileIds";

    String DOSSIER_ID_PATH_VARIABLE = "/{" + DOSSIER_ID + "}";
    String FILE_ID_PATH_VARIABLE = "/{" + FILE_ID + "}";
    String FALSE = "false";

    String HARD_DELETE_PATH = DELETE_PATH + "/hard-delete";
    String UNDELETE_PATH = DELETE_PATH + "/restore";


    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    @DeleteMapping(value = DELETE_PATH + DOSSIER_ID_PATH_VARIABLE + FILE_ID_PATH_VARIABLE)
    @Operation(summary = "Deletes a file for a given dossierId and FileId", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK")})
    void deleteFile(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId);


    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    @PostMapping(value = DELETE_PATH + DOSSIER_ID_PATH_VARIABLE)
    @Operation(summary = "Deletes a a list of files for a given dossierId", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK")})
    void deleteFiles(@PathVariable(DOSSIER_ID) String dossierId, @RequestBody List<String> fileIds);


    @ResponseBody
    @ResponseStatus(value = HttpStatus.OK)
    @Operation(summary = "Returns a downloadable byte stream of the original file with the specified fileId", description = "Use the optional \"inline\" request parameter to select, if this downloadAnnotated will be opened in the browser.")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Could not prepare file download.")})
    @GetMapping(value = DOWNLOAD_ORIGINAL_PATH + DOSSIER_ID_PATH_VARIABLE + FILE_ID_PATH_VARIABLE)
    ResponseEntity<?> downloadOriginal(@PathVariable(DOSSIER_ID) String dossierId,
                                       @PathVariable(FILE_ID) String fileId,
                                       @RequestParam(value = "inline", required = false, defaultValue = FALSE) boolean inline);


    @ResponseBody
    @ResponseStatus(value = HttpStatus.OK)
    @Operation(summary = "Returns a downloadable byte stream of the viewer document file with the specified fileId", description = "Use the optional \"inline\" request parameter to select, if this downloadAnnotated will be opened in the browser.")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Could not prepare file download.")})
    @GetMapping(value = DOWNLOAD_VIEWER_DOCUMENT_PATH + DOSSIER_ID_PATH_VARIABLE + FILE_ID_PATH_VARIABLE)
    ResponseEntity<?> downloadViewerDocument(@PathVariable(DOSSIER_ID) String dossierId,
                                             @PathVariable(FILE_ID) String fileId,
                                             @RequestParam(value = "inline", required = false, defaultValue = FALSE) boolean inline);


    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    @DeleteMapping(value = HARD_DELETE_PATH + DOSSIER_ID_PATH_VARIABLE)
    @Operation(summary = "Hard deletes an uploaded file.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "Successfully hard deleted the file."), @ApiResponse(responseCode = "404", description = "Not found")})
    void hardDeleteFiles(@PathVariable(DOSSIER_ID) String dossierId, @RequestParam(FILE_IDS) Set<String> fileIds);


    @ResponseBody
    @ResponseStatus(value = HttpStatus.CREATED)
    @PostMapping(value = UNDELETE_PATH + DOSSIER_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Restores an deleted file.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "File successfully restored."), @ApiResponse(responseCode = "400", description = "Incorrect dossier ID or file ID entered to restore file."), @ApiResponse(responseCode = "403", description = "Forbidden operation while restoring."), @ApiResponse(responseCode = "409", description = "Conflict occurred while restoring.")})
    void restoreFiles(@PathVariable(DOSSIER_ID) String dossierId, @RequestBody Set<String> fileIds);


    @ResponseStatus(value = HttpStatus.NO_CONTENT)
    @PostMapping(value = ROTATION_PATH + DOSSIER_ID_PATH_VARIABLE + FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "Rotates one or more pages for one file.", description = "None")
    @ApiResponses(value = {@ApiResponse(responseCode = "204", description = "Pages successfully rotated."), @ApiResponse(responseCode = "400", description = "Incorrect dossier ID, file ID, pages or rotation entered."), @ApiResponse(responseCode = "403", description = "Forbidden operation while rotating.")})
    void rotatePages(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @RequestBody RotatePagesRequest rotatePagesRequest);

}
