package com.brilliance.isc.common.tools.service.impl;

import com.brilliance.isc.common.tools.service.ObjectStroeToolService;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import java.io.*;
import java.util.List;

/**
 * 对象存储工具(支持本地NAS存储)
 *
 * <p>
 * 实例：
 * objectStroeToolService.saveObjectByStream(inputStream,"sstf/data/swtin/test.txt");
 * <p>
 * objectStroeToolService.getObjectFile("sstf/data/swtin/test.txt");
 * <p>
 * objectStroeToolService.saveObjectFileByString("this is test ","sstf/data/swtin/test1.txt","");
 * <p>
 * objectStroeToolService.moveObjectFile("sstf/data/swtin/test1.txt","sstf/data/swtin/test/test1.txt");
 * <p>
 * objectStroeToolService.removeObjectFile("sstf/data/swtin/test.txt");
 * </p>
 */
@Service
public class LocalFileStroeToolServiceImpl implements ObjectStroeToolService {

//    @Autowired
//    private PoinStoreService sstfStoreService;

    /**
     * 对象存储桶key
     */
    @Value("${sstf.object.storekey}")
    public String sstfStoreKey;

    /**
     * NAS存储key
     */
    @Value("${sstf.object.localkey}")
    public String localStoreKey;

    private static final AntPathMatcher pathMatcher = new AntPathMatcher();

    private static Logger logger = LoggerFactory.getLogger(LocalFileStroeToolServiceImpl.class);

    /**
     * 保存文件到NAS存储
     *
     * @param inputStream 需要保存的文件输入流
     * @param targetPath  对象存储上的目录
     */
    @Override
    public boolean saveNasFileByStream(InputStream inputStream, String targetPath) {
        return saveObjectFileByStream(localStoreKey, inputStream, targetPath);
    }

    /**
     * 保存文件到对象存储
     *
     * @param inputStream 需要保存的文件输入流
     * @param targetPath  对象存储上的目录
     */
    @Override
    public boolean saveObjectFileByStream(InputStream inputStream, String targetPath) {
        return saveObjectFileByStream(sstfStoreKey, inputStream, targetPath);
    }

    /**
     * 保存文件
     *
     * @param key         唯一标识
     * @param inputStream 需要保存的文件输入流
     * @param targetPath  对象存储上的目录
     */
    @SneakyThrows
    @Override
    public boolean saveObjectFileByStream(String key, InputStream inputStream, String targetPath) {
        File file = new File(targetPath);
        if (!file.exists()) {
            file.getParentFile().mkdirs();
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try (FileOutputStream fileOutputStream = new FileOutputStream(file);) {
            IOUtils.copy(inputStream, fileOutputStream);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(inputStream);
        }

        return true;
    }

    /**
     * 通过file对象保存到NAS存储
     *
     * @param file       需要上传的file对象
     * @param targetPath 目标路径
     */
    @Override
    public boolean saveNasFileByFile(File file, String targetPath) {
        return saveObjectFileByFile(localStoreKey, file, targetPath);
    }

    /**
     * 通过file对象保存到对象存储
     *
     * @param file       需要上传的file对象
     * @param targetPath 目标路径
     */
    @Override
    public boolean saveObjectFileByFile(File file, String targetPath) {
//        return saveObjectFileByFile(sstfStoreKey, file, targetPath);
        File targetFile = new File(targetPath);
        if (!targetFile.exists()) {
            targetFile.getParentFile().mkdirs();
        }
        try {
            targetFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        FileInputStream is = null;
        FileOutputStream os = null;
        try {
            is = new FileInputStream(file);
            os = new FileOutputStream(targetFile);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    /**
     * 通过file对象保存
     *
     * @param key        唯一标识
     * @param file       需要上传的file对象
     * @param targetPath 目标路径
     */
    @Override
    public boolean saveObjectFileByFile(String key, File file, String targetPath) {

        return true;
    }

    /**
     * 通过字符串保存文件到NAS存储
     *
     * @param content    文件内容
     * @param targetPath 目标路径
     * @param encoding   字符集
     */
    @Override
    public boolean saveNasFileByString(String content, String targetPath, String encoding) {
        return saveObjectFileByString(localStoreKey, content, targetPath, encoding);
    }

    /**
     * 通过字符串保存文件到对象存储
     *
     * @param content    文件内容
     * @param targetPath 目标路径
     * @param encoding   字符集
     */
    @Override
    public boolean saveObjectFileByString(String content, String targetPath, String encoding) {
        return saveObjectFileByString(sstfStoreKey, content, targetPath, encoding);
    }

    /**
     * 通过字符串保存文件
     *
     * @param key        唯一标识
     * @param content    文件内容
     * @param targetPath 目标路径
     * @param encoding   字符集
     */
    @SneakyThrows
    @Override
    public boolean saveObjectFileByString(String key, String content, String targetPath, String encoding) {
        File file = new File(targetPath);
        if (!file.exists()) {
            file.getParentFile().mkdirs();
        }
        file.createNewFile();
        FileWriter fileWriter = new FileWriter(file);
        fileWriter.write(content);
        fileWriter.close();
        return true;
    }

    /**
     * 分段上传大对象到对象存储
     *
     * @param localFilePath 本地文件路径
     * @param storeFilePath 对象存储路径
     */
    @Override
    public boolean saveMultiPartFile2Store(String localFilePath, String storeFilePath) {
        return true;
    }

    /**
     * 从NAS存储获取文件
     *
     * @param filePath 存储文件路径
     */
    @Override
    public File getNasFile(String filePath) {
        return getObjectFile(localStoreKey, filePath);
    }

    /**
     * 从对象存储获取文件
     *
     * @param filePath 存储文件路径
     */
    @Override
    public File getObjectFile(String filePath) {
        return getObjectFile(sstfStoreKey, filePath);
    }

    /**
     * 获取文件
     *
     * @param key      唯一标识
     * @param filePath 存储文件路径
     */
    @Override
    public File getObjectFile(String key, String filePath) {
        return new File(filePath);
    }

    /**
     * 从NAS存储读取文件
     *
     * @param filePath 存储文件路径
     */
    @Override
    public byte[] readNasFile(String filePath) {
        return readObjectFile(localStoreKey, filePath);
    }

    /**
     * 从对象存储读取文件
     *
     * @param filePath 存储文件路径
     */
    @Override
    public byte[] readObjectFile(String filePath) {
//        return readObjectFile(sstfStoreKey, filePath);
        try {
            File f = new File(filePath);
            if (!f.exists()) {
                throw new FileNotFoundException(filePath);
            }

            ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
            BufferedInputStream in = null;
            try {
                in = new BufferedInputStream(new FileInputStream(f));
                int buf_size = 1024;
                byte[] buffer = new byte[buf_size];
                int len = 0;
                while (-1 != (len = in.read(buffer, 0, buf_size))) {
                    bos.write(buffer, 0, len);
                }
                return bos.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            } finally {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                bos.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 读取文件内容成字节数组
     *
     * @param key      唯一标识
     * @param filePath 存储文件路径
     */
    @Override
    public byte[] readObjectFile(String key, String filePath) {
        return null;
    }

    /**
     * 获取Nas存储文件列表(包含子目录)
     *
     * @param dir 存储文件路径
     */
    @Override
    public File[] listNasFiles(String dir) {
        return listObjectFiles(localStoreKey, dir);
    }

    /**
     * 获取对象存储文件列表(包含子目录)
     *
     * @param dir 存储文件路径
     */
    @Override
    public File[] listObjectFiles(String dir) {
        return listObjectFiles(sstfStoreKey, dir);
    }

    /**
     * 获取指定目录文件列表，并通过ant风格路径筛选符合条件的文件，并返回
     *
     * @param dir     存储文件路径
     * @param antPath ant风格筛选路径
     * @return 返回符合条件的文件列表
     */
    @Override
    public File[] listObjectFilesByAntPatcher(String dir, String antPath) {
        return null;
    }

    /**
     * 获取指定目录的文件
     *
     * @param key 唯一标识
     * @param dir 存储文件路径
     */
    @Override
    public File[] listObjectFiles(String key, String dir) {
        return null;
    }

    /**
     * 从对象存储删除文件
     *
     * @param rmoveFilePath 文件目录
     */
    @Override
    public boolean removeNasFile(String rmoveFilePath) {
        return removeObjectFile(localStoreKey, rmoveFilePath);
    }

    /**
     * 从对象存储删除文件
     *
     * @param rmoveFilePath 文件目录
     */
    @Override
    public boolean removeObjectFile(String rmoveFilePath) {
        return removeObjectFile(sstfStoreKey, rmoveFilePath);
    }

    /**
     * 从存储删除文件
     *
     * @param key           唯一标识
     * @param rmoveFilePath 文件
     */
    @Override
    public boolean removeObjectFile(String key, String rmoveFilePath) {
        return true;
    }

    /**
     * 从对象存储批量删除文件
     *
     * @param files 待删除文件集合
     */
    @Override
    public boolean removeObjectFiles(List<String> files) {
        return removeObjectFiles(sstfStoreKey, files);
    }

    @Override
    public boolean copyNasFile(String filePath, String targetDir) {
        return false;
    }

    /**
     * 从对象存储批量删除文件
     *
     * @param key   唯一标识
     * @param files 待删除文件集合
     */
    @Override
    public boolean removeObjectFiles(String key, List<String> files) {
        return true;
    }

    /**
     * 清空对象存储指定目录文件
     *
     * @param dir 待清空目录
     */
    @Override
    public boolean cleanDir(String dir) {
        return false;
    }

    /**
     * 从Nas存储内目录移动文件
     *
     * @param filePath  源文件路径
     * @param targetDir 目标文件路径
     */
    @Override
    public boolean moveNasFile(String filePath, String targetDir) {
        File theFile = getNasFile(filePath);
        if (isExistNasFile(filePath)) {
            if (saveNasFileByFile(theFile, targetDir)) {
                return this.removeNasFile(filePath);
            }
        }
        return false;
    }

    @Override
    public boolean copyObjectFile(String filePath, String targetDir) {
        return false;
    }

    /**
     * 从对象存储内目录移动文件
     *
     * @param filePath  源文件路径
     * @param targetDir 目标文件路径
     */
    @Override
    public boolean moveObjectFile(String filePath, String targetDir) {
        File theFile = getObjectFile(filePath);
        if (isExistObjectFile(filePath)) {
            if (saveObjectFileByFile(theFile, targetDir)) {
                return this.removeObjectFile(filePath);
            }
        }
        return false;
    }

    /**
     * 判断MAS存储内是否存在此文件/目录
     *
     * @param filePath 文件路径
     */
    @Override
    public boolean isExistNasFile(String filePath) {
        return isExistObjectFile(localStoreKey, filePath);
    }

    /**
     * 判断对象存储内是否存在此文件/目录
     *
     * @param filePath 文件路径
     */
    @Override
    public boolean isExistObjectFile(String filePath) {
        return isExistObjectFile(sstfStoreKey, filePath);
    }

    /**
     * 判断储内是否存在此文件/目录
     *
     * @param key      唯一标识
     * @param filePath 文件路径
     */
    @Override
    public boolean isExistObjectFile(String key, String filePath) {
        return false;
    }


}