package com.dji.sample.media.controller;

import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.common.util.PicExifUtil;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.map.model.param.MediaDirQueryParam;
import com.dji.sample.map.model.param.MediaFileQueryParam;
import com.dji.sample.media.model.MediaDirDTO;
import com.dji.sample.media.model.MediaFileDTO;
import com.dji.sample.media.model.UploadResultDTO;
import com.dji.sample.media.service.IFileService;
import com.dji.sample.media.service.IMediaDirService;
import com.dji.sdk.cloudapi.map.CreateMapElementRequest;
import com.dji.sdk.cloudapi.map.CreateMapElementResponse;
import com.dji.sdk.common.HttpResultResponse;
import com.dji.sdk.common.PaginationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM;

/**
 * @author sean
 * @version 0.2
 * @date 2021/12/9
 */
@RestController
@RequestMapping("${url.media.prefix}${url.media.version}/files")
public class FileController {

    @Autowired
    private IFileService fileService;

    @Autowired
    private IMediaDirService dirService;

    /**
     * 获取工作空间下的所有目录信息
     * @param workspaceId
     * @return
     */
    @GetMapping("/{workspace_id}/dirs")
    public HttpResultResponse<PaginationData<MediaDirDTO>> getDirList(MediaDirQueryParam mediaDirQueryParam,
                                                                      @RequestParam(defaultValue = "1") Long page,
                                                                      @RequestParam(name = "page_size", defaultValue = "10") Long pageSize,
                                                                      @PathVariable(name = "workspace_id") String workspaceId
    ) {
        //PicExifUtil.getPicExif("test/全景图测试.jpg");
        PaginationData<MediaDirDTO> dirList = dirService.getMediaDirsPaginationByWorkspaceId(workspaceId, mediaDirQueryParam,page, pageSize);
        //补充容量大小
        if(!CollectionUtils.isEmpty(dirList.getList())) {
            Map<Integer, Long> sizeMap = fileService.getParentDirSize(dirList.getList().stream().map(dir -> dir.getId()).collect(Collectors.toList()));
            for(MediaDirDTO mediaDirDTO : dirList.getList()) {
                mediaDirDTO.setSize(sizeMap.get(mediaDirDTO.getId()));
            }
        }
        return HttpResultResponse.success(dirList);
    }

    /**
     * Get information about all the media files in this workspace based on the workspace id.
     * @param workspaceId
     * @return
     */
    @GetMapping("/{workspace_id}/files")
    public HttpResultResponse<PaginationData<MediaFileDTO>> getFilesList(MediaFileQueryParam mediaFileQueryParam,
                                                                         @RequestParam(defaultValue = "1") Long page,
                                                                         @RequestParam(name = "page_size", defaultValue = "10") Long pageSize,
                                                                         @PathVariable(name = "workspace_id") String workspaceId) {
        PaginationData<MediaFileDTO> filesList = fileService.getMediaFilesPaginationByWorkspaceId(workspaceId, mediaFileQueryParam, page, pageSize);
        return HttpResultResponse.success(filesList);
    }

    /**
     * 获取文件夹下的文件
     * @param workspaceId
     * @return
     */
    @GetMapping("/{workspace_id}/files/{dir_id}")
    public HttpResultResponse<PaginationData<MediaFileDTO>> getDirFilesList(@RequestParam(defaultValue = "1") Long page,
                                                                         @RequestParam(name = "page_size", defaultValue = "10") Long pageSize,
                                                                         @PathVariable(name = "workspace_id") String workspaceId,
                                                                         MediaFileQueryParam param,
                                                                         @PathVariable(name = "dir_id") String dirId) {
        PaginationData<MediaFileDTO> filesList = fileService.getMediaFilesPaginationByDirId(dirId, page, pageSize,param);
        return HttpResultResponse.success(filesList);
    }

    /**
     * Query the download address of the file according to the media file id,
     * and redirect to this address directly for download.
     * @param workspaceId
     * @param fileId
     * @param response
     */
    @GetMapping("/{workspace_id}/file/{file_id}/url")
    public void getFileUrl(@PathVariable(name = "workspace_id") String workspaceId,
                           @PathVariable(name = "file_id") String fileId, HttpServletResponse response) {

        try {
            URL url = fileService.getObjectUrl(workspaceId, fileId);
            response.sendRedirect(url.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询文件详情
     * @param workspaceId
     * @param fileId
     */
    @GetMapping("/{workspace_id}/file/{file_id}")
    public HttpResultResponse getDevice(@PathVariable("workspace_id") String workspaceId,
                                        @PathVariable("file_id") String fileId) {
        MediaFileDTO mediaFileDTO = fileService.getMediaFileByFileId(workspaceId,fileId);
        return mediaFileDTO == null ? HttpResultResponse.error("文件不存在") : HttpResultResponse.success(mediaFileDTO);
    }

    /**
     * 上传合成文件
     * @param file
     * @return
     */
    @PostMapping("/{workspace_id}/file/{dir_id}/upload")
    public HttpResultResponse uploadUnitedPictures(HttpServletRequest request, MultipartFile file,@PathVariable("dir_id") String dirId) {
        if (Objects.isNull(file)) {
            return HttpResultResponse.error("没有文件信息");
        }
        CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
        String workspaceId = customClaim.getWorkspaceId();
        String creator = customClaim.getUsername();
        fileService.uploadMediaFile(file, workspaceId,dirId, creator);
        return HttpResultResponse.success();
    }

    /**
     * 上传图片文件(zip)
     * @param file
     * @return
     */
    @PostMapping("/{workspace_id}/file/zip/upload")
    public HttpResultResponse importZipFile(HttpServletRequest request, MultipartFile file) {
        if (Objects.isNull(file)) {
            return HttpResultResponse.error("没有接收到任何文件");
        }
        CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
        String workspaceId = customClaim.getWorkspaceId();
        String creator = customClaim.getUsername();
        fileService.importZipFile(file, workspaceId, creator);
        return HttpResultResponse.success();
    }

    /**
     * 上传文件
     * @param file
     * @return
     */
    @PostMapping("/{workspace_id}/file/upload")
    public HttpResultResponse uploadFile(HttpServletRequest request, MultipartFile file) {
        if (Objects.isNull(file)) {
            return HttpResultResponse.error("没有文件信息");
        }
        CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
        String creator = customClaim.getUsername();
        UploadResultDTO resultDTO = fileService.uploadFile(file,creator);
        if(resultDTO == null) {
            return HttpResultResponse.error("上传失败");
        }
        return HttpResultResponse.success(resultDTO);
    }

    @GetMapping("/{workspace_id}/fileDownList")
    public void getFileStreamListByDirs(@PathVariable(name = "workspace_id") String workspaceId,
                                  @NotNull @Size(min = 1) @RequestParam(name = "id") List<String> ids,
                                    HttpServletResponse response) throws Exception {
        //String[] dirArray = dirIds.split(",");
        fileService.dowloadDirsToZip(workspaceId,ids,response);
    }

    @GetMapping("/{workspace_id}/downloadFiles")
    public void getFileStreamList(@PathVariable(name = "workspace_id") String workspaceId,
                                  @NotNull @Size(min = 1) @RequestParam(name = "id") List<String> ids,
                                  HttpServletResponse response) throws Exception {
        fileService.dowloadFilesToZip(workspaceId,ids,response);
    }

    @DeleteMapping("/{workspace_id}/deleteFiles")
    public HttpResultResponse deleteFiles(@PathVariable(name = "workspace_id") String workspaceId,
                                  @NotNull @Size(min = 1) @RequestParam(name = "id") List<String> ids,
                                          HttpServletResponse response) throws Exception {
        //String[] fileArray = fileIds.split(",");
        fileService.deleteFiles(ids);
        return HttpResultResponse.success();
    }

    /**
     * 更新媒体文件信息.
     * @param mediaFile
     * @param workspaceId
     * @param fileId
     * @return
     */
    @PutMapping("/{workspace_id}/updateFile/{file_id}")
    public HttpResultResponse updateFile(@RequestBody MediaFileDTO mediaFile,
                                           @PathVariable("workspace_id") String workspaceId,
                                           @PathVariable("file_id") String fileId) {
        mediaFile.setFileId(fileId);
        boolean isUpd = fileService.updateFile(mediaFile);
        return isUpd ? HttpResultResponse.success() : HttpResultResponse.error();
    }

    /**
     * 创建图片元素
     * @param workspaceId
     * @param fileId
     * @param req
     * @return
     */
    @PostMapping("/workspaces/{workspace_id}/createMapElement/{file_id}")
    HttpResultResponse<MediaFileDTO> createMapElement(
            @PathVariable(name = "workspace_id") String workspaceId,
            @PathVariable(name = "file_id") String fileId,
            HttpServletRequest req) {
        CustomClaim claims = (CustomClaim) req.getAttribute(TOKEN_CLAIM);
        MediaFileDTO mediaFile = fileService.getMediaFileByFileId(workspaceId,fileId);
        if(StringUtils.hasText(mediaFile.getElementId())) {
            return HttpResultResponse.error("该图片已存在地图元素，请不要重复创建！");
        }
        boolean isSucc = fileService.createMediaElement(workspaceId,claims.getUserType(),mediaFile);
        return isSucc ? HttpResultResponse.success(mediaFile) : HttpResultResponse.error();

    }

    /**
     * 删除图片元素
     * @param workspaceId
     * @param fileId
     * @return
     */
    @DeleteMapping("/workspaces/{workspace_id}/deleteMapElement/{file_id}")
    public HttpResultResponse deleteMapElement(@PathVariable(name = "workspace_id") String workspaceId,
                                               @PathVariable(name = "file_id") String fileId) {
        MediaFileDTO mediaFile = fileService.getMediaFileByFileId(workspaceId,fileId);
        if(!StringUtils.hasText(mediaFile.getElementId())) {
            return HttpResultResponse.success();
        }
        fileService.deleteMediaElement(workspaceId,mediaFile);
        return HttpResultResponse.success();
    }

    @DeleteMapping("/{workspace_id}/deleteDir")
    public HttpResultResponse deleteDir(@PathVariable(name = "workspace_id") String workspaceId,
                                          @NotNull @Size(min = 1) @RequestParam(name = "id") String id,
                                          HttpServletResponse response) throws Exception {
        fileService.deleteByDirId(id);
        return HttpResultResponse.success();
    }

    @DeleteMapping("/{workspace_id}/deleteFileById")
    public HttpResultResponse deleteFileById(@PathVariable(name = "workspace_id") String workspaceId,
                                        @NotNull @Size(min = 1) @RequestParam(name = "id") String id,
                                        HttpServletResponse response) throws Exception {
        fileService.deleteFileById(id);
        return HttpResultResponse.success();
    }
}
