package com.ssj.framework.files.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.ssj.bean.common.files.domain.FileInfo;
import com.ssj.framework.basic.utils.DateHelper;
import com.ssj.framework.core.common.service.BaseServiceImpl;
import com.ssj.framework.core.util.HttpRemote;
import com.ssj.framework.core.util.ImageTools;
import com.ssj.framework.core.util.OSSUtils;
import com.ssj.framework.core.util.PropertiesUtil;
import com.ssj.framework.idworker.IdWorker;
import com.ssj.framework.weixin.util.WeixinUtil;
import com.ssj.taskthread.Task;
import com.ssj.taskthread.ThreadPool;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@Service("fileInfoService")
public class FileInfoServiceImpl extends BaseServiceImpl<FileInfo, String> implements FileInfoService {
	
	private   Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
    private FileInfoDao fileInfoDao;
	@Override
	public PagingAndSortingRepository<FileInfo, String> getDao() {
		return fileInfoDao;
	}
	@Override
	public List<FileInfo> uploadFilePicture(String userId,Map<String, MultipartFile> files) throws Exception {
		String imgFilePath = getSavePath() + "/";
		List<FileInfo> list = commonMethodOfUploadFile(userId,files,imgFilePath,null);
		return list;
	}

	@Override
	public List<FileInfo> uploadFile(String userId,Map<String, MultipartFile> files,String filePath)throws Exception {
		// 创建文件夹
		File f = new File(filePath);
		if (!f.exists()) {
			f.mkdirs();
		}
		List<FileInfo> list = commonMethodOfUploadFile(userId,files,filePath,"originalName");
		return list;
	}

	public List<FileInfo> commonMethodOfUploadFile(String userId,Map<String, MultipartFile> files,String filePath,String fileName) throws Exception{
		List<FileInfo> list =new ArrayList<>();
		for (Map.Entry<String, MultipartFile> entity : files.entrySet()) {
			MultipartFile fileItem = entity.getValue();
			// 得到当前文件
			if (fileItem == null) {
				continue;
			}
			// 得到文件的完整路径
			String  path = fileItem.getOriginalFilename();
			// 得到文件的大小
			long size = fileItem.getSize();
			// 得到去除路径的文件名
			String t_name = path.substring(path.lastIndexOf("/") + 1);
			// 得到文件的扩展名(无扩展名时将得到全名)
			String t_ext = t_name.substring(t_name.lastIndexOf(".") + 1);
			logger.info("文件上传格式t_ext----"+t_ext);
			if(t_ext !=null && t_ext.contains("image%")){
				t_ext ="jpg";
			}
			logger.info("文件上传格式t_ext----"+t_ext);
		//	InputStream is = null;
			try {
				FileInfo  fileInfo = new FileInfo();
			//	is = fileItem.getInputStream();
				//String fileCode = encodeSHA256Hex(input2byte(is));
				String file_name;
				//取文件原来名称
				if ("originalName".equals(fileName)) {
					file_name = t_name;
				} else {
					//重新生成文件名
					file_name = IdWorker.generateId() + "." + t_ext;
				}

				File f = new File(filePath + file_name);
				// 保存文件
				FileCopyUtils.copy(fileItem.getBytes(), f);
				/*BufferedImage sourceImg = ImageIO.read(new FileInputStream(f));
				if(sourceImg!=null){
					fileInfo.setFileHeight(sourceImg.getHeight());
					fileInfo.setFileWidth(sourceImg.getWidth());
				}*/
				String ps= OSSUtils.uploadInputStream(fileItem.getInputStream(),
						(filePath + file_name).replaceAll(PropertiesUtil.getValue("file_save_path"), ""));
				logger.info("阿里oss返回的路径="+ps);


				fileInfo.setUserId(userId);
			//	is.close(); // 关闭 流，否则 无法删除临时文件，一直被java所持有
				// 保存的最终文件完整路径(使用文件唯一标识作为文件名)

				// 添加到数据库
				//fileInfo.setFileCode(fileCode);
				fileInfo.setFilePath((filePath + file_name).replaceAll(PropertiesUtil.getValue("file_save_path"), ""));
				fileInfo.setFileSize(String.format("%.1f", size / 1024.0));
				fileInfo.setFileExt(t_ext);
				fileInfo.setFileName(t_name);
				fileInfo.setCreatedDate(new Date());
				fileInfo.setFileThumPath(PropertiesUtil.getValue("STATIC_FILE_URL")+fileInfo.getFilePath());
				fileInfoDao.save(fileInfo);
				list.add(fileInfo);
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				/*if (is != null) {
					is.close();
				}
				is = null;*/
				fileItem = null;
			}
		}
		return list;
	}
    /**
     * 获取保存目录 按年/月/日 区分
     */
    private static String getSavePath() {
        String savePath = PropertiesUtil.getValue("file_save_path");
        // 当前日期(按月保存)
        String date = DateHelper.formatDateByFormat(new Date(), "yyyy/MM/dd");
        savePath = savePath +  date;
        // 创建文件夹
        File f = new File(savePath);
        if (!f.exists()) {
            f.mkdirs();
        }
        return savePath;
    }
	
	@Override
	public void upConchFileLog(List<MultipartFile> files, String derver) throws Exception {
		
		//设备日志保存
		// /www/data/upload/conch/设备号/日期+文件名.后缀  /www/data/upload/conch/123456/2018-5-9_xxx.log
		String savePath = PropertiesUtil.getValue("file_save_path");
        // 保存路径  /www/data/upload/conch/derver
        savePath = savePath + "/conch/"+ derver+ "/";
        // 创建文件夹
        File logFilePath = new File(savePath);
        if (!logFilePath.exists()) {
        	logFilePath.mkdirs();
        }
		for (MultipartFile fileItem : files) {
           // 得到当前文件
           if (fileItem == null) {
               continue;
           }
           // 得到文件的完整路径
           String  path = fileItem.getOriginalFilename();
           logger.info("文件名path"+path);
           // 得到去除路径的文件名
           String t_name = path.substring(path.lastIndexOf("/") + 1);
           logger.info("文件名"+t_name );
           // 得到文件的扩展名(无扩展名时将得到全名)
           String t_ext = t_name.substring(t_name.lastIndexOf(".") + 1);
           logger.info("文件的扩展名"+t_ext );
           if(t_ext !=null && t_ext.contains("image%")){
        	   t_ext ="jpg";
           }
           InputStream is = null;
           try {
        	   is = fileItem.getInputStream();
        	   String fileCode = DateHelper.getUserDate("yyyy-MM-dd")+"_"+encodeSHA256Hex(input2byte(is));
        	   is.close(); // 关闭 流，否则 无法删除临时文件，一直被java所持有
        	   // 保存的最终文件完整路径(使用文件唯一标识作为文件名)
               String file_name = fileCode + "." + t_ext;
        	   File f = new File(savePath + file_name);
        	   // 保存文件
               FileCopyUtils.copy(fileItem.getBytes(), f);
               logger.info("upConchFileLog="+f.getAbsolutePath() );
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
                if (is != null) {
                    is.close();
                }
                is = null;
                fileItem = null;
            }
		}
	}
	@Override
	public FileInfo saveFileInfo(String userId, String picPath,
			String fileName) {
		
		
		FileInfo   fileInfo = new FileInfo();
		fileInfo.setUserId(userId);
		fileInfo.setFilePath(picPath.replaceAll(PropertiesUtil.getValue("file_save_path"), ""));
		fileInfo.setCreatedDate(new Date());
		fileInfo.setFileName(fileName);
		fileInfo.setFileThumPath(PropertiesUtil.getValue("STATIC_FILE_URL")+fileInfo.getFilePath());
		if(fileName!=null){
			fileInfo.setFileExt(FilenameUtils.getExtension(fileName));
		}
		/* InputStream is = null;
         try {
        	 logger.info(picPath);
        	 File picture = new File(picPath);
        	 fileInfo.setFileSize(String.format("%.1f", picture.length() / 1024.0));
        	 logger.info("file"+String.format("%.1f", picture.length() / 1024.0));
        	 logger.info("fileSize"+fileInfo.getFileSize());
        	 is = new FileInputStream(picture); 
        	 BufferedImage sourceImg = ImageIO.read(is);
        	 if(sourceImg!=null){
        		 fileInfo.setFileHeight(sourceImg.getHeight());
        		 fileInfo.setFileWidth(sourceImg.getWidth());
        	 }
       
      	      String fileCode = encodeSHA256Hex(input2byte(is));
	           is.close(); // 关闭 流，否则 无法删除临时文件，一直被java所持有
	            fileInfo.setFileCode(fileCode);
	            
	        } catch (Exception e) {
	            e.printStackTrace();
	        }finally {
                if (is != null) {
                    try {
						is.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
                }
                is = null;
            }*/

	        fileInfoDao.save(fileInfo);
	        return fileInfo;
	}
	@Override
	public List<FileInfo> saveFilePicture(String userId, String[] picPaths,
			String[] fileNames) {
		List<FileInfo> pictures = new ArrayList<FileInfo>();

        for (int i = 0; i < picPaths.length; i++) {
        	 logger.info("picPaths="+picPaths[i]);
        	FileInfo fileInfo = new FileInfo();
        	fileInfo.setFilePath(picPaths[i].replaceAll(PropertiesUtil.getValue("file_save_path"), ""));
    		fileInfo.setCreatedDate(new Date());
    		fileInfo.setFileName(fileNames[i]);
    		fileInfo.setFileThumPath(PropertiesUtil.getValue("STATIC_FILE_URL")+fileInfo.getFilePath());
    		fileInfo.setUserId(userId);
    		if(fileNames[i]!=null){
    			fileInfo.setFileExt(FilenameUtils.getExtension(fileNames[i]));
    		}
    		
    		/* InputStream is = null;
             try {
            	 File picture = new File(picPaths[i]);
            	 is = new FileInputStream(picture); 
            	 
            	 BufferedImage sourceImg = ImageIO.read(is);
            	 if(sourceImg!=null){
            		 fileInfo.setFileHeight(sourceImg.getHeight());
            		 fileInfo.setFileWidth(sourceImg.getWidth());
            	 }
            	 fileInfo.setFileSize(String.format("%.1f", picture.length() / 1024.0));
            	 logger.info("file"+String.format("%.1f", picture.length() / 1024.0));
            	 logger.info("fileSize"+fileInfo.getFileSize());
          	      String fileCode = encodeSHA256Hex(input2byte(is));
    	          is.close(); // 关闭 流，否则 无法删除临时文件，一直被java所持有
    	          fileInfo.setFileCode(fileCode);
    	            
    	        } catch (Exception e) {
    	            e.printStackTrace();
    	        }finally {
                    if (is != null) {
                        try {
    						is.close();
    					} catch (IOException e) {
    						e.printStackTrace();
    					}
                    }
                    is = null;
                }*/

            pictures.add(fileInfo);
        }

        //入库
        fileInfoDao.save(pictures);

        return pictures;
	}



	public List<FileInfo> saveFilePicture(String userId, String[] picPaths,
			String[] fileNames,String[] fileCodes) {
		List<FileInfo> pictures = new ArrayList<FileInfo>();

        for (int i = 0; i < picPaths.length; i++) {
        	 logger.info("picPaths="+picPaths[i]);
        	FileInfo fileInfo = new FileInfo();
        	fileInfo.setFilePath(picPaths[i].replaceAll(PropertiesUtil.getValue("file_save_path"), ""));
    		fileInfo.setCreatedDate(new Date());
    		fileInfo.setFileName(fileNames[i]);
    		fileInfo.setFileThumPath(PropertiesUtil.getValue("STATIC_FILE_URL")+fileInfo.getFilePath());
    		fileInfo.setUserId(userId);
    		if(fileNames[i]!=null){
    			fileInfo.setFileExt(FilenameUtils.getExtension(fileNames[i]));
    		}
		/*	if(fileCodes[i]!=null){
				fileInfo.setFileCode(fileCodes[i]);
			}*/
    	/*	 InputStream is = null;
             try {
            	 File picture = new File(picPaths[i]);
            	 is = new FileInputStream(picture);

            	 BufferedImage sourceImg = ImageIO.read(is);
            	 if(sourceImg!=null){
            		 fileInfo.setFileHeight(sourceImg.getHeight());
            		 fileInfo.setFileWidth(sourceImg.getWidth());
            	 }
            	 fileInfo.setFileSize(String.format("%.1f", picture.length() / 1024.0));
            	 logger.info("file"+String.format("%.1f", picture.length() / 1024.0));
            	 logger.info("fileSize"+fileInfo.getFileSize());

    	          is.close(); // 关闭 流，否则 无法删除临时文件，一直被java所持有


    	        } catch (Exception e) {
    	            e.printStackTrace();
    	        }finally {
                    if (is != null) {
                        try {
    						is.close();
    					} catch (IOException e) {
    						e.printStackTrace();
    					}
                    }
                    is = null;
                }*/

            pictures.add(fileInfo);
        }

        //入库
        fileInfoDao.save(pictures);

        return pictures;
	}
	@Override
	public List<FileInfo> uploadFilePicture(String userId,List<MultipartFile> files)  {
		//保存文件
        String[] savePaths = ImageTools.uploadFile(files);
        String[] fileNames = new String[files.size()];
        String[] fileCodes =new String [files.size()];
        int i = 0;
	/*	InputStream is = null;
		try{
			for (MultipartFile fileItem : files) {
				fileNames[i] = fileItem.getOriginalFilename();
				is = fileItem.getInputStream();
				fileCodes[i]= encodeSHA256Hex(input2byte(is));
				logger.error("fileCodes=)"+fileCodes[i]);
				i++;
			}
			is.close();
		} catch (Exception e) {
			e.printStackTrace();

		}finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			is = null;
		}*/


        if (savePaths.length > 0) {
            //文件信息入库
            List<FileInfo> fileInfoList = saveFilePicture(userId, savePaths, fileNames,fileCodes);
            if (fileNames.length == fileInfoList.size()) {
            	return fileInfoList;         
            } else {
                return null;
            }
        } else {
            return null;
        }
	}


	

	@Override
	public List<FileInfo> findFileInfoByDate(String date) {
		return fileInfoDao.findFileInfoByDate(date);
	}
	private  final byte[] input2byte(InputStream inStream) throws IOException {
		ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
		byte[] buff = new byte[100];
		int rc = 0;
		while ((rc = inStream.read(buff, 0, 100)) > 0) {
			swapStream.write(buff, 0, rc);
		}
		byte[] in2b = swapStream.toByteArray();
		return in2b;
	}
	
	/**
	 * SHA-256消息摘要算法,返回十六进制字符串
	 */
	private String encodeSHA256Hex(byte[] data) throws Exception {
		return DigestUtils.sha256Hex(data);
	}
	@Override
	public void deleteByFilePath(String filePath) {
		 String savePath = PropertiesUtil.getValue("file_save_path");
		File file = new File(savePath+filePath);
		if(file.exists()){
            file.delete();
            logger.info("文件：" + filePath + " 删除成功！");
            logger.info("文件：" + file.getAbsolutePath() + " 删除成功！");
        }else{
            logger.info("文件：" + file.getAbsolutePath() + " 不存在！");
        }
		fileInfoDao.deleteByFilePath(filePath);
		
		
	}

	@Override
	public void updateFileCode(String fileCode,int star,int end) throws  Exception {
		List<FileInfo>  list=fileInfoDao.findFileInfoByFileCode(fileCode,star,end);

		String savePath = PropertiesUtil.getValue("file_save_path");
		for (FileInfo fileInfo:list) {
			logger.info("文件：" + fileInfo );
			/*File picture = new File(savePath+fileInfo.getFilePath());
			InputStream is =  new FileInputStream(picture);
			String newfileCode =encodeSHA256Hex(input2byte(is));
			is.close();
			logger.info("newfileCode：" + newfileCode );
			fileInfo.setFileCode(newfileCode);*/
			this.save(fileInfo);
		}

	}

	@Override
	public boolean fileIsExists(String filePath, String userId) {
	   Long count=	fileInfoDao.countFileInfoByFilePathAndUserId(userId,filePath);
		return count>0?false:true;
	}

	@Override
	public void upExceptionLog(List<MultipartFile> files, String mobileOS, int platformType) throws Exception {
		//前端日志上传公共接口异常保存
		// /www/files/data/upload/ssj/哪个端/哪个手机系统/日期+文件名.后缀  /www/files/data/upload/ssj/parent/android/2018-5-9_xxx.log
		String savePath = PropertiesUtil.getValue("file_save_path");
		// 保存路径  /www/files/data/upload/ssj/哪个端
		String platform = "parent";
		if(platformType == 1) {
			platform = "parent";
		}else if(platformType == 2) {
			platform = "teacher";
		}
		savePath = savePath + "/ssj/"+ platform+ "/"+ mobileOS +"/";
		// 创建文件夹
		File logFilePath = new File(savePath);
		if (!logFilePath.exists()) {
			logFilePath.mkdirs();
		}
		for (MultipartFile fileItem : files) {
			// 得到当前文件
			if (fileItem == null) {
				continue;
			}
			// 得到文件的完整路径
			String  path = fileItem.getOriginalFilename();
			logger.info("文件名path"+path);
			// 得到去除路径的文件名
			String t_name = path.substring(path.lastIndexOf("/") + 1);
			logger.info("文件名"+t_name );
			// 得到文件的扩展名(无扩展名时将得到全名)
			String t_ext = t_name.substring(t_name.lastIndexOf(".") + 1);
			logger.info("文件的扩展名"+t_ext );
			if(t_ext !=null && t_ext.contains("image%")){
				t_ext ="jpg";
			}
			InputStream is = null;
			try {
				is = fileItem.getInputStream();
				String fileCode = DateHelper.getUserDate("yyyy-MM-dd")+"_"+encodeSHA256Hex(input2byte(is));
				is.close(); // 关闭 流，否则 无法删除临时文件，一直被java所持有
				// 保存的最终文件完整路径(使用文件唯一标识作为文件名)
				String file_name = fileCode + "." + t_ext;
				File f = new File(savePath + file_name);
				// 保存文件
				FileCopyUtils.copy(fileItem.getBytes(), f);
				logger.info("upConchFileLog="+f.getAbsolutePath() );
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				if (is != null) {
					is.close();
				}
				is = null;
				fileItem = null;
			}
		}
	}



	@Override
	public List<FileInfo> uploadFilePicturePd(String userId,List<MultipartFile> files)  {

		List<FileInfo> pictures = new ArrayList<FileInfo>();
		for (MultipartFile fileItem : files) {

			//图片保存文件名
			String originalFile = fileItem.getOriginalFilename();
			String ext = originalFile.substring(originalFile.lastIndexOf("."));
			if(ext !=null && ext.contains("image%")){
				ext =ImageTools.SUFF_JPG;
			}
			try {

				Map<String,Object>  map = new HashMap<String,Object>();
				map.put("deviceNo",userId);
				String  result= HttpRemote.GETMethod(WeixinUtil.url+"/ctq/getOssfsToken", map);
				JSONObject json = JSON.parseObject(result);
				Integer status= json.getInteger("status");
				String uploadPath ="";
				if(status ==0){
					 uploadPath = "/"+json.getString("uploadPath");
				}else{
					logger.error("获取上海培典阿里云OSS上传Token--失败不上传文件");
					uploadPath =  DateHelper.formatDateByFormat(new Date(), "yyyy/MM/dd")+"/";
				}

				String imgFilePath = PropertiesUtil.getValue("file_save_path")+uploadPath  ;
				// 创建文件夹
				File f = new File(imgFilePath);

				if (!f.exists()) {
					f.mkdirs();
				}
				String saveFileName =IdWorker.generateId() + ext;
				ImageTools.uploadFilePd(fileItem,imgFilePath + saveFileName);
				FileInfo fileInfo = new FileInfo();
				fileInfo.setFilePath(uploadPath+saveFileName);
				fileInfo.setCreatedDate(new Date());
				fileInfo.setFileName(originalFile);
				fileInfo.setFileThumPath(PropertiesUtil.getValue("STATIC_FILE_URL")+fileInfo.getFilePath());
				fileInfo.setUserId(userId);
				if(originalFile!=null){
					fileInfo.setFileExt(FilenameUtils.getExtension(originalFile));
				}
				/*InputStream is =fileItem.getInputStream();
				fileInfo.setFileCode(encodeSHA256Hex(input2byte(is)));
				is.close(); // 关闭 流，否则 无法删除临时文件，一直被java所持有
				BufferedImage sourceImg = ImageIO.read(fileItem.getInputStream());
				if(sourceImg!=null){
					fileInfo.setFileHeight(sourceImg.getHeight());
					fileInfo.setFileWidth(sourceImg.getWidth());
				}

				fileInfo.setFileSize(String.format("%.1f", fileItem.getSize() / 1024.0));
				logger.info("file"+String.format("%.1f", fileItem.getSize() / 1024.0));
				logger.info("fileSize"+fileInfo.getFileSize());*/

				if(status ==0){
					String accessKeyId = json.getString("accessKeyId");
					String secretKeyId = json.getString("secretKeyId");
					String securityToken = json.getString("securityToken");
					ThreadPool.getInstance().addTask(new SyncUploadpdOSS(accessKeyId,secretKeyId,securityToken,uploadPath+saveFileName,userId,fileItem));
				}else{
					logger.info("不上传上海oss图片="+fileInfo);
				}
				pictures.add(fileInfo);

			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		//入库
		 fileInfoDao.save(pictures);
         return pictures;

	}

}

class SyncUploadpdOSS extends Task {
	private static Logger logger = LoggerFactory.getLogger(SyncUploadpdOSS.class);
	private String accessKeyId ;
	private String secretKeyId;
	private String securityToken;
	private String uploadPath;
	private String userId;
	private MultipartFile files;


	public SyncUploadpdOSS(String accessKeyId  ,String secretKeyId , String securityToken,String uploadPath,String userId,MultipartFile files) {
		super();
		this.accessKeyId=accessKeyId;
		this.secretKeyId=secretKeyId;
		this.securityToken=securityToken;
		this.uploadPath=uploadPath;
		this.userId=userId;
		this.files =files;
	}

	@Override
	public void run() {
		try {

			String endpoint = "https://oss-accelerate.aliyuncs.com";
			logger.error("accessKeyId="+accessKeyId);
			logger.error("secretKeyId="+secretKeyId);
			logger.error("securityToken="+securityToken);
			logger.error("uploadPath="+uploadPath);
			logger.error("userId="+userId);
			OSSClient ossClient = new OSSClient(endpoint, new DefaultCredentialProvider(accessKeyId, secretKeyId, securityToken),null);
			try {
				String keys=uploadPath.substring(0,1);
				//String uploadPaths =uploadPath;
				if("/".equals(keys)){
					uploadPath=uploadPath.replaceFirst(keys, "");
				}
				ossClient.putObject(WeixinUtil.bucketName, uploadPath,files.getInputStream());
			} catch (Exception e) {
				logger.error("培典OSS上传异常..."+e);
			}finally{
				ossClient.shutdown();
			}
		} catch (Exception e) {
			logger.error("推送信息保存异常...");
		}
	}


}

