package sgc.portal.base.view;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;

/**
 * 해당 view를 사용하기 위해서는 Controller 클래스내 메소드에서 ModelAndView 클래스를 리턴해야 한다.
 *
 * @author YongSang
 * @version 1.0.0
 * @since 2020. 9. 6.
 */
@Slf4j
class FileDownloadView extends AbstractView {
    /**
     * The constant FILE_ATTRIBUTE_NAME.
     */
    private static final String FILE_ATTRIBUTE_NAME = "file";
    /**
     * The constant FILENAME_ATTRIBUTE_NAME.
     */
    private static final String FILENAME_ATTRIBUTE_NAME = "filename";

    /**
     * Instantiates a new File download view.
     */
    private FileDownloadView() {
        setContentType(MediaType.APPLICATION_OCTET_STREAM.toString());
    }

    /**
     * AbstractView의 renderMergedOutputModel() 메소드를 오버라이드 함
     * @see org.springframework.web.servlet.view.AbstractView#renderMergedOutputModel(java.util.Map, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (model.get(FILE_ATTRIBUTE_NAME) != null) {
            InputStream is;
            OutputStream out = response.getOutputStream();

            int size = -1;
            String filename = (String) model.get(FILENAME_ATTRIBUTE_NAME);
            if (model.get(FILE_ATTRIBUTE_NAME) instanceof File) {
                File file = (File) model.get(FILE_ATTRIBUTE_NAME);
                size = (int) file.length();
                filename = (model.get(FILENAME_ATTRIBUTE_NAME) != null) ? (String) model.get(FILENAME_ATTRIBUTE_NAME) : file.getName();

                try(InputStream lis = Files.newInputStream(Paths.get(filename))) {
                    is = lis;
                }
            } else {
                is = (InputStream) model.get(FILE_ATTRIBUTE_NAME);
            }

            response.setContentType(getContentType());
            response.setContentLength(size);
            response.setHeader("Content-Transfer-Encoding", "binary");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(filename, "utf-8") + "\";");

            FileCopyUtils.copy(is, out);

            out.flush();
        }
    }
}