package com.ejweb.modules.front.upload.api;

import com.ejweb.conf.ErrorCode;
import com.ejweb.conf.GConstants;
import com.ejweb.core.api.ResponseBean;
import com.ejweb.core.utils.IdGen;
import com.ejweb.modules.front.upload.util.ReportAttachmentUtils;
import com.ejweb.modules.report.entity.ReportAttachmentEntity;
import com.ejweb.modules.sys.service.LogService;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

;

/**
 * Created by BrianHolsen on 2017-07-11 at 17:19.
 */
@Controller
@RequestMapping("/api/front/file")
public class FileController {

    private class UploadResultBean {
        public String id;
        public String uri;
        public int size;
        public String extention;
        public String fileName;
    }

    // <editor-fold desc="<===private fields=========================================================================>">
    @Autowired
    private LogService logService;

    private static final String savePath = GConstants.getValue("file.upload.dir");
    private static final String pathSeparator = GConstants.getValue("upload.path.separator", "\\");
    private static final String allowedExt = GConstants.getValue("upload.extension", "");
    private String downloadFileMethodName = "downloadFile";
    private String downloadFileParamName = "file";
    private String downloadImageMethodName = "downloadImage";
    private String downloadImageParamName = "file";
    private String viewServer = GConstants.getValue("file.prefix.url");
    // </editor-fold>

    // <editor-fold desc="<===getters & setters======================================================================>">
    public String getDownloadFileMethodName() {
        return downloadFileMethodName;
    }

    public void setDownloadFileMethodName(String downloadFileMethodName) {
        this.downloadFileMethodName = downloadFileMethodName;
    }

    public String getDownloadFileParamName() {
        return downloadFileParamName;
    }

    public void setDownloadFileParamName(String downloadFileParamName) {
        this.downloadFileParamName = downloadFileParamName;
    }

    public String getDownloadImageMethodName() {
        return downloadImageMethodName;
    }

    public void setDownloadImageMethodName(String downloadImageMethodName) {
        this.downloadImageMethodName = downloadImageMethodName;
    }

    public String getDownloadImageParamName() {
        return downloadImageParamName;
    }

    public void setDownloadImageParamName(String downloadImageParamName) {
        this.downloadImageParamName = downloadImageParamName;
    }
    // </editor-fold>

    /**
     * 上传文件
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping("/upload")
    public ResponseBean upload(HttpServletRequest request) {
        ResponseBean response = new ResponseBean();
        boolean isMutipart = ServletFileUpload.isMultipartContent(request);
        if (isMutipart) {
            String currentUri = request.getRequestURI();
            int index = currentUri.lastIndexOf("/");
            String baseUri = currentUri.substring(0, index);

            FileItemFactory factory = new org.apache.commons.fileupload.disk.DiskFileItemFactory();
            ServletFileUpload fileUpload = new ServletFileUpload(factory);
            try {
                List<FileItem> fileItems = fileUpload.parseRequest(request);
                if (fileItems.size() < 1) {
                    response.setStatus(ErrorCode.NO_FILE_UPLOADED);
                    response.setMessage(ErrorCode.NO_FILE_FOUND_DESC);
                } else if (fileItems.size() == 1) {
                    FileItem item = fileItems.get(0);
                    UploadResultBean resultBean = this.storeFile(item.getName(), baseUri, item.get());
                    if (resultBean == null) {
                        response.setStatus(ErrorCode.WRITE_FILE_FAIL);
                        response.setMessage(ErrorCode.WRITE_FILE_FAIL_DESC);
                    } else {
                        response.setData(resultBean);
                    }
                } else {
                    List<UploadResultBean> beans = new ArrayList<>();
                    for (FileItem item : fileItems) {
                        if(!item.isFormField()){
                            UploadResultBean resultBean = this.storeFile(item.getName(), baseUri, item.get());
                            beans.add(resultBean);
                        }
                    }
                    response.setData(beans);
                }
            } catch (FileUploadException e) {
                //this.logService.logError(e.getMessage());
                e.printStackTrace();
            }

        }
        return response;
    }

    /**
     * 下载文件
     * @param request
     * @param response
     * @param file
     */
    @ResponseBody
    @RequestMapping("/downloadFile")
    public void downloadFile(HttpServletRequest request, HttpServletResponse response, String file) {
        if (file == null || file.isEmpty()) {
            response.setStatus(HttpStatus.NOT_FOUND.value());
        }
        byte[] bts = this.getFile(file);
        if (bts == null) {
            response.setStatus(HttpStatus.NOT_FOUND.value());
        }
        response.setContentType("application/force-download");
        response.setContentLength(bts.length);
        response.setHeader("Content-Transfer-Encoding", "binary");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + file + "\"");
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            outputStream.write(bts);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(outputStream);
        }
    }

    @ResponseBody
    public byte[] downloadImage(String file) {
        return this.getFile(file);
    }

    // <editor-fold desc="<===private methods========================================================================>">
    private UploadResultBean storeFile(String name, String baseUri, byte[] bts) {
        UploadResultBean bean = new UploadResultBean();
//        String id = UUIDUtil.uuid();
        bean.extention = this.getExtension(name);
        bean.size = bts.length;
        bean.fileName = name;
        String pathRel = "web/" + name;
        File file = new File(this.savePath  + pathRel);

        try {
            FileUtils.writeByteArrayToFile(file, bts);
        } catch (IOException e) {
            //this.logService.logError(e.getMessage());
            e.printStackTrace();
            return null;
        }

        String method = "";
        String param = "";
        switch (bean.extention.trim().toLowerCase()) {
            case ".bmp":
            case ".jpg":
            case ".jpeg":
            case ".png":
            case ".gif":
                method = this.getDownloadImageMethodName();
                param = this.getDownloadImageParamName();
                if (method == null || method.isEmpty()) {
                    method = "downloadImage";
                }
                if (param == null || param.isEmpty()) {
                    param = "file";
                }
                break;
            default:
                method = this.getDownloadFileMethodName();
                param = this.getDownloadFileParamName();
                if (method == null || method.isEmpty()) {
                    method = "downloadFile";
                }
                if (param == null || param.isEmpty()) {
                    param = "file";
                }
                break;
        }
        String id = IdGen.uuid();
        bean.id = id;
        bean.uri = viewServer +  pathRel;
        //记录上传信息
        ReportAttachmentEntity attachmentEntity = new ReportAttachmentEntity();
        attachmentEntity.setId(id);
        attachmentEntity.setAttachmentName(name);
        attachmentEntity.setAttachmentSize(bean.size);
        attachmentEntity.setAttachmentPath(viewServer  + pathRel);
        attachmentEntity.setAttachmentType("0");
        ReportAttachmentUtils.add(attachmentEntity);
        return bean;
    }

    private byte[] getFile(String name) {
        String path = this.savePath + this.pathSeparator + name.replace("_", this.pathSeparator);
        try {
            byte[] bts = FileUtils.readFileToByteArray(new File(path));
            return bts;
        } catch (IOException e) {
            //this.logService.logError(e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    private String getStoreRefDir() {
//        SimpleDateFormat df = new SimpleDateFormat("yyyy" + pathSeparator + "MM" + pathSeparator + "dd");
//        String str = df.format(new Date()) + this.pathSeparator;
        return "";
    }

    private String getExtension(String name) {
        if (name == null || name.isEmpty()) {
            return "";
        }
        int index = name.lastIndexOf(".");
        if (index > 0) {
            return name.substring(index);
        }
        return "";
    }
    // </editor-fold>
}