package com.artfess.file.controller;


import com.artfess.base.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.activation.MimetypesFileTypeMap;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.JsonNode;
import com.artfess.base.annotation.ApiGroup;
import com.artfess.base.attachment.AttachmentService;
import com.artfess.base.attachment.AttachmentServiceFactory;
import com.artfess.base.constants.ApiGroupConsts;
import com.artfess.base.exception.NotFoundException;
import com.artfess.base.handler.MultiTenantHandler;
import com.artfess.base.handler.MultiTenantIgnoreResult;
import com.artfess.base.util.AppUtil;
import com.artfess.base.util.BeanUtils;
import com.artfess.base.util.FileUtil;
import com.artfess.base.util.JsonUtil;
import com.artfess.file.attachmentService.FtpAttachmentServiceImpl;
import com.artfess.file.model.DefaultFile;
import com.artfess.file.persistence.manager.FileManager;
import com.artfess.file.service.FilePreview;
import com.artfess.file.service.FilePreviewFactory;
import com.artfess.file.util.AppFileUtil;
import com.artfess.file.util.FileUtils;

/**
 * 附件在线预览
 * @company 广州宏天软件股份有限公司
 * @author:lj
 * @date:2018年6月14日
 */
@RestController
@RequestMapping("/file/onlinePreviewController/v1")
@Api(tags="附件在线预览")
@ApiGroup(group= {ApiGroupConsts.GROUP_SYSTEM})
@SuppressWarnings({ "rawtypes" })
public class OnlinePreviewController {
	@Resource
	FilePreviewFactory previewFactory;
	@Resource
	FileManager fileManager;
	@Resource
	FileUtils fileUtils;
	@Value("${file.file.dir}")
	String fileDir;

	@RequestMapping(value="onlinePreview", method=RequestMethod.GET, produces={"application/json; charset=utf-8" })
	@ApiOperation(value = "附件在线预览", httpMethod = "GET", notes = "附件在线预览")
	public JsonNode onlinePreview(HttpServletRequest request, HttpServletResponse response,@ApiParam(name="fileId",value="附件ID")@RequestParam String fileId) throws Exception {
		Map<String,String> map=new HashMap<String,String>();
		DefaultFile fileMode = fileManager.get(fileId);
		if(fileMode!=null){
			AttachmentServiceFactory attachmentHandlerFactory = AppUtil.getBean(AttachmentServiceFactory.class);
            String saveType = AppFileUtil.getSaveType(fileMode.getProp6());
			if(StringUtil.isEmpty(saveType)){
                saveType = AppFileUtil.getFileSaveTypeByConfig(BeanUtils.isNotEmpty(fileMode)?fileMode.getBizCode():"");
            }
            AttachmentService attachmentService = attachmentHandlerFactory.getCurrentServices(saveType);
			//特殊场景，附件上传方式是ftpsaveType，word套打生成的文件是磁盘存储，下载套打文件时特殊处理
			if(attachmentService instanceof FtpAttachmentServiceImpl && DefaultFile.SAVE_TYPE_FOLDER.equals(fileMode.getStoreType())){
				attachmentService = attachmentHandlerFactory.getCurrentServices(DefaultFile.SAVE_TYPE_FOLDER);
			}
			boolean ref=attachmentService.chekckFile(fileMode,BeanUtils.isNotEmpty(fileMode)?fileMode.getProp6():"");
			if(ref){
				FilePreview filePreview = previewFactory.get(fileMode);
				String Result=filePreview.filePreviewHandle(fileMode, map);
				map.put("result",Result);
				map.remove("project");
			}else{
				map.put("result","error");
			}
		}
		JsonNode object=JsonUtil.toJsonNode(map);
		return  object;
	}



	@RequestMapping(value="getFileByPathAndId_{fileId}_{ext}", method=RequestMethod.GET, produces={"application/json; charset=utf-8" })
	@ApiOperation(value = "根据ID和类型找到处理后的附件", httpMethod = "GET", notes = "根据ID和类型找到附件")
	public void getFileByPathAndId(HttpServletResponse response, @PathVariable(name="fileId") String fileId, @PathVariable(name="ext") String ext) throws IOException{
		String fullPath=fileDir+fileId+"."+ext;
        String type = "text/html;charset="+getCharset(fullPath);
        if("pdf".equals(ext)){
            type="application/pdf";
        }
		response.setContentType(type);
		byte[] bytes = FileUtil.readByte(fullPath);
		if(bytes!=null&&bytes.length>0){
			response.getOutputStream().write(bytes);
		}

	}




	@RequestMapping(value="getFileById_{fileId}", method=RequestMethod.GET, produces={"application/json; charset=utf-8" })
	@ApiOperation(value = "根据文件ID找到上传过的文件", httpMethod = "GET", notes = "根据文件ID找到上传过的文件")
	public void getFileById(HttpServletRequest request, HttpServletResponse response, @PathVariable(name="fileId") String fileId) throws Exception {
		DefaultFile file = null;
		try (MultiTenantIgnoreResult setThreadLocalIgnore = MultiTenantHandler.setThreadLocalIgnore()) {
			file = fileManager.get(fileId);
		}
		if (BeanUtils.isEmpty(file)) {
			throw new NotFoundException(String.format("未找到fileId为: %s 的文件", fileId));
		}
		String fileName = file.getFileName() + "." + file.getExtensionName();
		String filedisplay = URLEncoder.encode(fileName, "utf-8");
		response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
		response.addHeader("filename", filedisplay);
		response.setHeader("Access-Control-Allow-Origin", "*");
		String type = new MimetypesFileTypeMap().getContentType(new File(file.getFilePath()));
		response.setContentType(type);
		fileManager.downloadFile(fileId, response.getOutputStream());
	}




	//根据文件路径获取文件编码格式
    public static String getCharset(String pathName) {
        File file = new File(pathName);
        if (!file.exists()) {
            return "";
        }
        String charset = "GBK";
        byte[] first3Bytes = new byte[3];
        BufferedInputStream bis = null;
        try {
            boolean checked = false;
            bis = new BufferedInputStream(new FileInputStream(file));
            bis.mark(0);
            int read = bis.read(first3Bytes, 0, 3);
            if (read == -1)
                return charset;
            if (first3Bytes[0] == (byte) 0xFF
                    && first3Bytes[1] == (byte) 0xFE) {
                charset = "UTF-16LE";
                checked = true;
            } else if (first3Bytes[0] == (byte) 0xFE
                    && first3Bytes[1] == (byte) 0xFF) {
                charset = "UTF-16BE";
                checked = true;
            } else if (first3Bytes[0] == (byte) 0xEF
                    && first3Bytes[1] == (byte) 0xBB
                    && first3Bytes[2] == (byte) 0xBF) {
                charset = "UTF-8";
                checked = true;
            }
            bis.reset();
            if (!checked) {
                while ((read = bis.read()) != -1) {
                    if (read >= 0xF0)
                        break;
                    if (0x80 <= read && read <= 0xBF)
                        break;
                    if (0xC0 <= read && read <= 0xDF) {
                        read = bis.read();
                        if (0x80 <= read && read <= 0xBF)
                            continue;
                        else
                            break;
                    } else if (0xE0 <= read && read <= 0xEF) {
                        read = bis.read();
                        if (0x80 <= read && read <= 0xBF) {
                            read = bis.read();
                            if (0x80 <= read && read <= 0xBF) {
                                charset = "UTF-8";
                                break;
                            } else
                                break;
                        } else
                            break;
                    }
                }
            }

            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bis.close();
            } catch (IOException e) {
            }
        }

        return charset;
    }
}
