package cn.exploring.engine.server.core.storage;

import cn.exploring.engine.server.core.util.CharUtil;
import cn.exploring.engine.server.db.domain.WxStorage;
import cn.exploring.engine.server.db.service.WxStorageService;
import org.apache.commons.collections.keyvalue.DefaultMapEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;

import java.io.InputStream;
import java.nio.file.Path;
import java.util.Map;
import java.util.stream.Stream;

/**
 * 提供存储服务类，所有存储服务均由该类对外提供
 */
public class StorageService {
    private String active;
    private Storage storage;
    /**
     * 本地存储
     */
    private LocalStorage localStorage;
    @Autowired
    private WxStorageService wxStorageService;

    public String getActive() {
        return active;
    }

    public void setActive(String active) {
        this.active = active;
    }

    public Storage getStorage() {
        return storage;
    }

    public void setStorage(Storage storage) {
        this.storage = storage;
    }

    public LocalStorage getLocalStorage() {
        return localStorage;
    }

    public void setLocalStorage(LocalStorage localStorage) {
        this.localStorage = localStorage;
    }

    /**
     * 存储一个文件对象
     *
     * @param inputStream   文件输入流
     * @param contentLength 文件长度
     * @param contentType   文件类型
     * @param fileName      文件索引名
     */
    public String store(InputStream inputStream, long contentLength, String contentType, String fileName, String key) {
        storage.store(inputStream, contentLength, contentType, key);

        String url = generateUrl(key);
        WxStorage storageInfo = new WxStorage();
        storageInfo.setName(fileName);
        storageInfo.setSize((int) contentLength);
        storageInfo.setType(contentType);
        storageInfo.setKey(key);
        storageInfo.setUrl(url);
        wxStorageService.add(storageInfo);

        return url;
    }

    /**
     * 只记数据库（本地保存时，压缩后的文件用。疑问压缩方法中已经保存，这里只记数据库就行了）
     *
     * @param contentLength 文件长度
     * @param contentType   文件类型
     * @param fileName      文件索引名
     */
    public String dbStore(long contentLength, String contentType, String fileName, String key) {
        String url = generateUrl(key);
        WxStorage storageInfo = new WxStorage();
        storageInfo.setName(fileName);
        storageInfo.setSize((int) contentLength);
        storageInfo.setType(contentType);
        storageInfo.setKey(key);
        storageInfo.setUrl(url);
        wxStorageService.add(storageInfo);

        return url;
    }

    /**
     * 只存本地，不记数据库（保存原始文件的时候用到）
     *
     * @param inputStream   文件输入流
     * @param contentLength 文件长度
     * @param contentType   文件类型
     * @param fileName      文件索引名
     */
    public String localStore(InputStream inputStream, long contentLength, String contentType, String fileName, String key) {
        localStorage.store(inputStream, contentLength, contentType, key);

        String path = localStorage.generatePath(key);
        System.out.println("----localStore path------- " + path);

        return path;
    }

    /**
     * 只存本地，又记数据库（用户上传运动记录数据时用到）
     *
     * @param inputStream   文件输入流
     * @param contentLength 文件长度
     * @param contentType   文件类型
     * @param fileName      文件索引名
     */
    public String localDbStore(InputStream inputStream, long contentLength, String contentType, String fileName, String key) {
        localStorage.store(inputStream, contentLength, contentType, key);

        String url = localStorage.generateUrl(key);
        WxStorage storageInfo = new WxStorage();
        storageInfo.setName(fileName);
        storageInfo.setSize((int) contentLength);
        storageInfo.setType(contentType);
        storageInfo.setKey(key);
        storageInfo.setUrl(url);
        wxStorageService.add(storageInfo);

        return url;
    }

    /**
     * 存储一个文件对象到storage
     *
     * @param inputStream   文件输入流
     * @param contentLength 文件长度
     * @param contentType   文件类型
     * @param fileName      文件索引名
     */
    public String storageStore(InputStream inputStream, long contentLength, String contentType, String fileName, String key) {
        storage.store(inputStream, contentLength, contentType, key);

        String url = generateUrl(key);

        return url;
    }

    public String generateKey(String originalFilename) {
        int index = originalFilename.lastIndexOf('.');
        String suffix = originalFilename.substring(index);

        String key = null;
        WxStorage storageInfo = null;

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

        return key;
    }

    /**
     * 生成原始文件和新文件两个key，两个key的扩展名可能不一样
     * @param originalFilename
     * @return
     */
    public Map.Entry<String, String> generateKeyEntry(String originalFilename) {
        int index = originalFilename.lastIndexOf('.');
        String suffix = originalFilename.substring(index);

        String pre = null;
        String key = null;
        WxStorage storageInfo = null;

        do {
            pre = CharUtil.getRandomString(20);
            key = pre + suffix;
            storageInfo = wxStorageService.findByKey(key);
        }
        while (storageInfo != null);

        return new DefaultMapEntry(key, pre + ".jpg");
    }

    /**
     * 生成唯一路径名
     * @param originalFilename
     * @return
     */
    public String generateUniquePath(String originalFilename) {
        String randomPathStr = null;
        WxStorage storageInfo = null;

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

        return randomPathStr;
    }

    public Stream<Path> loadAll() {
        return storage.loadAll();
    }

    public Path load(String keyName) {
        return storage.load(keyName);
    }

    public Resource loadAsResource(String keyName) {
        return storage.loadAsResource(keyName);
    }

    public void delete(String keyName) {
        storage.delete(keyName);
    }

    private String generateUrl(String keyName) {
        return storage.generateUrl(keyName);
    }
}
