package com.dgtis.dorm.manager.db.service;


import com.dgtis.dorm.manager.db.dao.StorageMapper;
import com.dgtis.dorm.manager.db.domain.Storage;
import com.dgtis.dorm.manager.db.util.CharUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class FileSystemStorageService implements StorageService {

    @Autowired
    private AlumniRecordStorageService alumniRecordStorageService;
    @Autowired
    private StorageMapper storageMapper;

    private static String file_http_path;
    private static String file_absolute_path;
    public static Path rootLocation;

    //= Paths.get(file_absolute_path);
    //private static final Path rootLocation = Paths.get("/home/steve/images");
    @Value("${file.absolute.path}")
    public void setRootLocation(String file_absolute_path) {
        System.out.println("file_absolute_path" + file_absolute_path);
        FileSystemStorageService.file_absolute_path = file_absolute_path;
        FileSystemStorageService.rootLocation = Paths.get(file_absolute_path);
    }

    @Value("${file.http.path}")
    public void setFile_http_path(String file_http_path) {
        FileSystemStorageService.file_http_path = file_http_path;
    }

    private String generateUrl(String newPath, String newFileName) {
        System.out.println("file_http_path" + file_http_path);
        return file_http_path + newPath + "/" + newFileName;
    }

    // private static final Path rootLocation = Paths.get("/home/steve/images");

    //private String generateUrl(String newPath,String key){
    //    return "http://xiaoyou.dgtis.com/images/"+newPath+"/"+key;
    //}

    private final String generateKey() {
        String key = null;
        Storage storageInfo = null;

        do {
            key = CharUtil.getRandomString(20);
            storageInfo = alumniRecordStorageService.findByKey(key);
        }
        while (storageInfo != null);

        return key;
    }

    @Override
    public Storage store(MultipartFile file, String imgBelongs) {
        Storage storageInfo = new Storage();
        String originalFilename = file.getOriginalFilename();
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        String contentType = file.getContentType();
        String key = generateKey();
        String[] fileSuffix = originalFilename.split("\\.");
        String newFileName = key + "." + fileSuffix[fileSuffix.length - 1];

        try {

            //创建目录
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            String ymd = sdf.format(new Date());
            String newPath = contentType.split("/")[0] + "/" + ymd;
            Path path = Files.createDirectories(FileSystemStorageService.rootLocation.resolve(newPath));
            //创建文件
            Files.copy(inputStream, path.resolve(newFileName));


            //添加数据记录
            String url = generateUrl(newPath, newFileName);

            storageInfo.setOldName(originalFilename);
            storageInfo.setNewName(newFileName);
            storageInfo.setSize((int) file.getSize());
            storageInfo.setType(contentType);
            storageInfo.setFilePath("/" + newPath + "/" + newFileName);
            storageInfo.setCreateTime(LocalDateTime.now());
            storageInfo.setModifyTime(LocalDateTime.now());
            storageInfo.setKey(key);
            storageInfo.setUrl(url);
            storageInfo.setImgBelongs(imgBelongs);
            alumniRecordStorageService.insertSelective(storageInfo);

        } catch (IOException e) {
            throw new RuntimeException("Failed to store file " + newFileName, e);
        }

        return storageInfo;
    }

    /**
     * @descption: 根据key查询storage
     * @param: [key]
     * @return: com.dgtis.dorm.manager.db.domain.Storage
     * @auther: koucx
     * @date: 2019/5/13 0013 11:49
     */
    @Override
    public Storage selectByKey(Storage key) {
        return storageMapper.selectOneByExample(key);
    }

    /**
     * 创建文件以及添加表记录
     *
     * @param file
     */
    @Override
    public Storage store(MultipartFile file) {
        return store(file, null);
    }


    /**
     * 获取文件完整的Path
     *
     * @param filePath 带有文件名的path
     * @return
     */
    @Override
    public Path load(String filePath) {
        return Paths.get(FileSystemStorageService.rootLocation.toString()).resolve(filePath);
    }


    @Override
    public Resource loadAsResource(String filename) {
        try {
            Path p = FileSystemStorageService.rootLocation;
            Path file = Paths.get(p.toString() + filename);
            Resource resource = new UrlResource(file.toUri());
            if (resource.exists() || resource.isReadable()) {
                return resource;
            } else {
                throw new RuntimeException("Could not read file: " + filename);

            }
        } catch (MalformedURLException e) {
            throw new RuntimeException("Could not read file: " + filename, e);
        }
    }

    /**
     * 删除文件以及表记录
     *
     * @param fileId
     */
    @Override
    public void deleteById(Integer fileId) {
        Storage storage = alumniRecordStorageService.selectByPrimaryKey(fileId);
        String filePath = storage.getFilePath().substring(1, storage.getFilePath().length());
        Path file = load(filePath);
        try {
            Files.delete(file);
            alumniRecordStorageService.deleteByPrimaryKey(fileId);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 方法描述  存储二维码
     *
     * @author huanghaoqi
     * @date 2018年12月06日 11:53:55
     */
    @Override
    public Storage storeQrCode(InputStream inputStream, String fileName) {
        Storage storageInfo = new Storage();
        String key = generateKey();
        String newFileName = key + ".png";
        String contentType = "image/png";
        try {
            //创建目录
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
            String ymd = sdf.format(new Date());
            String newPath =  "qrcode/" + ymd;
            Path path = Files.createDirectories(FileSystemStorageService.rootLocation.resolve(newPath));
            //创建文件
            Files.copy(inputStream, path.resolve(newFileName));

            //添加数据记录
            String url = generateUrl(newPath, newFileName);

            storageInfo.setOldName(fileName);
            storageInfo.setNewName(newFileName);
            storageInfo.setSize((inputStream.available()));
            storageInfo.setType(contentType);
            storageInfo.setFilePath("/" + newPath + "/" + newFileName);
            storageInfo.setCreateTime(LocalDateTime.now());
            storageInfo.setModifyTime(LocalDateTime.now());
            storageInfo.setKey(key);
            storageInfo.setUrl(url);
            storageInfo.setImgBelongs(null);
            alumniRecordStorageService.insertSelective(storageInfo);
        } catch (IOException e) {
            throw new RuntimeException("Failed to store file " + newFileName, e);
        }

        return storageInfo;
    }


    /**
     * 下载压缩包
     *
     * @return
     * @throws IOException
     */
    @Override
    public Resource downloadZip(List<String> fileIds, String fileName) {
        Path p = FileSystemStorageService.rootLocation;
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            String zipFileName = p.toString() + "/" + fileName;
            fos = new FileOutputStream(zipFileName);
            zos = new ZipOutputStream(new BufferedOutputStream(fos));
            byte[] bufs = new byte[1024 * 10];
            List<Storage> storageList = storageMapper.selectByKeys(fileIds);
            if (!CollectionUtils.isEmpty(storageList)) {
                for (Storage storage : storageList) {
                    File file = new File(p.toString() + "/" + storage.getFilePath());
                    ZipEntry zipEntry = new ZipEntry(storage.getOldName());
                    zos.putNextEntry(zipEntry);
                    fis = new FileInputStream(file);
                    bis = new BufferedInputStream(fis, 1024 * 10);
                    int read = 0;
                    while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
                        zos.write(bufs, 0, read);
                    }
                }
            }
            return loadAsResource("/"+fileName);
        } catch (Exception e) {
            throw new RuntimeException("Failed to store file " + fileName, e);
        } finally {
            try {
                if (null != bis) {
                    bis.close();
                }
                if (null != zos) {
                    zos.close();
                }
                if (null != fis) {
                    fis.close();
                }
                if (null != fos) {
                    fos.close();
                }

            } catch (IOException e) {
                throw new RuntimeException("Failed to store file " + fileName, e);
            }
        }
    }
}