package com.dbnt.faisp.config;

import com.dbnt.faisp.main.faRpt.service.FaRptService;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.service.FishingBoatService;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.service.SailorService;
import com.dbnt.faisp.main.fpiMgt.affair.service.AffairService;
import com.dbnt.faisp.main.fpiMgt.affairPlan.service.PlanService;
import com.dbnt.faisp.main.fpiMgt.affairResult.service.ResultService;
import com.dbnt.faisp.main.fpiMgt.sri.service.SriService;
import com.dbnt.faisp.main.ivsgtMgt.boardInvestigation.service.BoardInvestigationService;
import com.dbnt.faisp.main.publicBoard.service.PublicBoardService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@RestController
@RequiredArgsConstructor
@RequestMapping("/file")
public class FileController {

  private final FaRptService faRptService;
  private final PlanService planService;
  private final PublicBoardService publicBoardService;
  private final AffairService affairService;
  private final ResultService resultService;
  private final BoardInvestigationService boardInvestigationService;
  private final FishingBoatService fishingBoatService;
  private final SriService sriService;

  @Value("${file.dir}")
  protected String fileDir;
  @Value("${file.dir.editor}")
  protected String editorPath;

  @GetMapping("/editorFileDisplay")
  public ResponseEntity<Resource> editorFileDisplay(HttpServletRequest request,
                                              HttpServletResponse response,
                                              String fileNm) {

    String pathStr = fileDir+File.separator+editorPath+File.separator+fileNm;
    Resource resource = new FileSystemResource(pathStr);
    if(!resource.exists()){
      return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
    HttpHeaders header = new HttpHeaders();
    Path filePath = null;
    try {
      filePath = Paths.get(pathStr);
      header.add("Content-type", Files.probeContentType(filePath));
    }catch (IOException e){
      e.printStackTrace();
    }
    return new ResponseEntity<Resource>(resource, header, HttpStatus.OK);
  }

  @GetMapping("/fileDisplay")
  public ResponseEntity<Resource> fileDisplay(HttpServletRequest request,
                                              HttpServletResponse response,
                                              String board,
                                              Integer parentKey,
                                              Integer fileSeq) {
    FileInfo fileInfo = getFileInfo(board, parentKey, fileSeq);
    String pathStr = fileInfo.getSavePath()+fileInfo.getConvNm();
    Resource resource = new FileSystemResource(pathStr);
    if(!resource.exists()){
      return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
    HttpHeaders header = new HttpHeaders();
    Path filePath = null;
    try {
      filePath = Paths.get(pathStr);
      header.add("Content-type", Files.probeContentType(filePath));
    }catch (IOException e){
      e.printStackTrace();
    }
    return new ResponseEntity<Resource>(resource, header, HttpStatus.OK);
  }

  @GetMapping("/fileDownload")
  public void fileDownload(HttpServletRequest request,
                           HttpServletResponse response,
                           String board,
                           Integer parentKey,
                           Integer fileSeq) {

    FileInfo fileInfo = getFileInfo(board, parentKey, fileSeq);
    BufferedInputStream in;
    BufferedOutputStream out;
    try {
      File file = new File(fileInfo.getSavePath(), fileInfo.getConvNm());

      setDisposition(fileInfo.getFullName(), request, response);
      in = new BufferedInputStream(new FileInputStream(file));
      out = new BufferedOutputStream(response.getOutputStream());
      FileCopyUtils.copy(in, out);
      out.flush();
      if(out!=null) out.close();
      if(in!=null )in.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  private FileInfo getFileInfo(String board, Integer parentKey, Integer fileSeq){
    FileInfo downloadFile = null;
    switch (board){
      case "faRpt":
        downloadFile = faRptService.selectFaRptFile(parentKey, fileSeq);
        break;
      case "affairPlan":
        downloadFile = planService.selectPlanFile(parentKey, fileSeq);
        break;
      case "publicFile":
        downloadFile = publicBoardService.selectPublicFile(parentKey, fileSeq);
        break;
      case "affair":
        downloadFile = affairService.selectAffairFile(parentKey, fileSeq);
        break;
      case "affairResult":
        downloadFile = resultService.selectResultFile(parentKey, fileSeq);
        break;
      case "ivsgt":
        downloadFile = boardInvestigationService.selectIvsgtFile(parentKey, fileSeq);
        break;
      case "sailor":
        downloadFile = fishingBoatService.selectSailorFile(parentKey, fileSeq);
        break;
      case "sri":
        downloadFile = sriService.selectFaSriFile(parentKey, fileSeq);
      break;
    }
    return downloadFile;
  }
  private void setDisposition(String filename, HttpServletRequest request, HttpServletResponse response) throws IOException {
    String browser = getBrowser(request);

    String dispositionPrefix = "attachment; filename=";
    String encodedFilename = null;

    if (browser.equals("MSIE")) {
      encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
    } else if (browser.equals("Trident")) { // IE11 문자열 깨짐 방지
      encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
    } else if (browser.equals("Firefox")) {
      encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
    } else if (browser.equals("Opera")) {
      encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
    } else if (browser.equals("Chrome")) {
      StringBuffer sb = new StringBuffer();
      for (int i = 0; i < filename.length(); i++) {
        char c = filename.charAt(i);
        if (c > '~') {
          sb.append(URLEncoder.encode("" + c, "UTF-8"));
        } else {
          sb.append(c);
        }
      }
      encodedFilename = sb.toString();
    } else {
      throw new IOException("Not supported browser");
    }

    response.setHeader("Content-Disposition", dispositionPrefix + encodedFilename);

    if ("Opera".equals(browser)) {
      response.setContentType("application/octet-stream;charset=UTF-8");
    }
  }

  private String getBrowser(HttpServletRequest request) {
    String header = request.getHeader("User-Agent");
    if (header.indexOf("MSIE") > -1) {
      return "MSIE";
    } else if (header.indexOf("Trident") > -1) { // IE11 문자열 깨짐 방지
      return "Trident";
    } else if (header.indexOf("Chrome") > -1) {
      return "Chrome";
    } else if (header.indexOf("Opera") > -1) {
      return "Opera";
    }
    return "Firefox";
  }
}
