package sgc.portal.base.storage.web;

import sgc.portal.base.storage.SubpathFactory;
import sgc.portal.base.storage.model.FileBucket;
import sgc.portal.base.storage.service.StorageService;
import sgc.portal.security.annotation.Secured;
import sgc.portal.security.annotation.SecurityPolicy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 파일 업로드 콘트롤러
 *
 * @author YongSang
 * @version 1.0.0
 * @since  2020. 9. 5.
 */
@RestController
@Secured(policy = SecurityPolicy.SESSION)
public class FileUploadController {
    @Autowired
    private StorageService service;

    /**
     * 파일 업로드를 처리
     *
     * @param request MultipartHttpServletRequest 객체
     * @param id 파일 아이디를 같이 전달할 경우에는 기존 파일 목록에 첨부파일을 추가 (첨부파일 수정 시 보통 사용)
     * @param type date or default 두 값이 전달
     *        파일이 저장되는 위치는 기본으로 yyyy/mm 형태를 지원하고 추가적으로 특정한 디렉토리를 만들고
     *        그 하위에 위치시킬 수 있다. abc,123을 파라미터가 전달될 경우 abc/123/ 2020/9 하위에 파일이 업로드된다.
     *        type을 default주고 abc,123 파라미터를 전달할 경우 abc/123 하위에 파일이 업로드된다.
     * @param others 파일 업로드 패스
     * @return 업로드된 파일 정보
     */
    @PostMapping({"/files", "/mobile/api/files"})
    public List<FileBucket> upload(HttpServletRequest request, @RequestParam(required = false) String id,
            @RequestParam(required = false, defaultValue = "date") String type,
            @RequestParam(required = false) String... others) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        return service.store(id, new ArrayList<>(fileMap.values()), SubpathFactory.create(type, others));
    }

    @PostMapping("/apiFiles")
    @Secured(policy = SecurityPolicy.NONE)
    public List<FileBucket> apiUpload(HttpServletRequest request, @RequestParam(required = false) String id,
                                   @RequestParam(required = false, defaultValue = "date") String type,
                                   @RequestParam(required = false) String... others) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        return service.store(id, new ArrayList<>(fileMap.values()), SubpathFactory.create(type, others));
    }

    /**
     * 업로드된 파일의 정보를 얻어온다 (단건)
     *
     * @param id 파일아이디
     * @return 파일정보
     */
    @GetMapping("/files/{id}")
    public FileBucket load(@PathVariable String id) {
        return service.load(id);
    }

    /**
     * 업로드된 파일의 정보를 얻어온다 (여러건 중 한 개)
     *
     * @param id 파일아이디
     * @param backNumber 파일번호
     * @return 파일정보
     */
    @GetMapping("/files/{id}/{backNumber}")
    public FileBucket load(@PathVariable String id, @PathVariable Integer backNumber) {
        return service.load(id, backNumber);
    }

    /**
     * 업로드된 파일들의 정보를 얻어온다 (여러건)
     *
     * @param id 파일아이디
     * @return 파일정보들
     */
    @GetMapping({"/files/{id}/all", "/mobile/api/files/{id}/all"})
    @Secured(policy = SecurityPolicy.NONE)
    public List<FileBucket> loadAll(@PathVariable String id) {
        return service.loadAll(id);
    }

    /**
     * 업로드된 파일들의 정보를 쎔네일과 같이 얻어온다 (여러건)
     *
     * @param id 파일아이디
     * @param thumbType 썸네일 형태
     * @return 파일정보들
     */
    @GetMapping({"/files/{id}/thumb/{thumbType}", "/mobile/api/files/{id}/thumb/{thumbType}"})
    @Secured(policy = SecurityPolicy.NONE)
    public List<FileBucket> loadAllWithThumbnail(@PathVariable String id, @PathVariable String thumbType) {
        return service.loadAllWithThumbnail(id, thumbType);
    }
    
    /**
     * 업로드된 파일을 삭제한다. (단건)
     *
     * @param id 파일아이디
     */
    @DeleteMapping("/files/{id}")
    public void remove(@PathVariable String id) {
        service.remove(id);
    }

    /**
     * 업로드된 파일을 삭제한다. (여러건 중 한 개)
     * 아래 @DeleteMapping URI를 호출할 경우에는 반드시
     * 파라미터에 _method=delete 파라미터가 있어야 함.
     *
     * @param id 파일아이디
     * @param backNumbers 파일번호
     */
    @DeleteMapping({"/files/{id}/{backNumbers}","/mobile/api/files/{id}/{backNumbers}"})
    public void remove(@PathVariable String id, @PathVariable List<Integer> backNumbers) {
        service.remove(id, backNumbers);
    }

    /**
     * 업로드된 파일을 모두 삭제한다.
     *
     * @param id 파일아이디
     */
    @DeleteMapping({"/files/{id}/all", "/mobile/api/files/{id}/all" } )
    public void removeAll(@PathVariable String id) {
        service.removeAll(id);
    }

    /**
     * 삭제된(플래그 처리된) 업로드 파일을 물리적으로 모두 삭제한다.
     *
     * @param date 파일아이디
     */
    @DeleteMapping("/files/delete/{date}")
    public void deleteAll(@PathVariable String date) {
        service.deleteAll(date);
    }

    /**
     * 업로드된 파일을 삭제한다. (단건)
     *
     * @param id 파일아이디
     */
    @PostMapping("/files/{id}")
    public void remove2(@PathVariable String id) {
        service.remove(id);
    }
}