import streamSaver from "streamsaver";
import "streamsaver/examples/zip-stream.js";
import JSZip from 'jszip';
import FileSaver from 'file-saver';
import axios from 'axios'
// import store from '@/store'
streamSaver.mitm = `${window.location.origin}/mitm.html?version=2.0.0`
function getFile(url) {
    return new Promise((resolve, reject) => {
        axios.get(url, {
            responseType: 'blob',
        }).then(res => {
            resolve(res.data)
        }).catch(err => {
            reject(err)
        })
    })
}
function addFilesRecursively(zip, structure) {
    Object.keys(structure).forEach((key) => {
        if (typeof structure[key] === "object" && !structure[key].size) {
            // 创建子文件夹
            const subFolder = zip.folder(key);
            addFilesRecursively(subFolder, structure[key]);
        } else {
            // 添加文件
            zip.file(key, structure[key], { binary: true });
        }
    });
};
function createFloders(obj, arr, r) {
    let i = arr.shift()
    if (arr.length <= 0) {
        obj[i] = r
    } else {
        if (!obj[i]) {
            obj[i] = {}
        }
        createFloders(obj[i], arr, r)
    }
}
function downLoadFileConcurrency(obj, arr, callback) {
    return new Promise(resolve => {
        let list = arr.splice(0, 6)
        let all = []
        list.forEach(file => {
            let res = getFile(file.url).then(r => {
                const arr = file.name.split('/')
                createFloders(obj, arr, r)
                if (callback) {
                    callback({
                        type: 'downLoad',
                        data: r
                    })
                }
                // zip.file(fileName, r, { binary: true });
            })
            all.push(res)
        })
        Promise.all(all).then(async () => {
            if (arr.length <= 0) {
                resolve(true)
            } else {
                let res = await downLoadFileConcurrency(obj, arr, callback)
                resolve(res)
            }
        }).catch(err => {
            if (callback) {
                callback({
                    type: 'error'
                })
            }
            console.log(err)
        })
    })
}
function zipFilesJsZip(zipName, files, obj = {}, callback) {
    return new Promise(async resolve => {
        try {
            if (callback) {
                callback({
                    type: 'start'
                })
            }
            console.log("同步下载打包开始时间：" + new Date());
            files = formatFiles(files)
            const zip = new JSZip();
            // let all = []
            let res = await downLoadFileConcurrency(obj, files, callback)
            if (res) {
                if (callback) {
                    callback({
                        type: 'downLoaded',
                    })
                }
                addFilesRecursively(zip, obj)
                zip.generateAsync({
                    type: "blob",
                    compression: "DEFLATE",  // STORE：默认不压缩 DEFLATE：需要压缩
                    compressionOptions: {
                        level: 9               // 压缩等级1~9    1压缩速度最快，9最优压缩方式
                    }
                }).then((res) => {
                    if (callback) {
                        callback({
                            type: 'zipEnd',
                        })
                    }
                    console.log("同步下载打包结束时间：" + new Date());
                    FileSaver.saveAs(res, zipName) // 利用file-saver保存文件
                }).catch(err => {
                    console.log("打包失败", err)
                })
            }
        } catch (err) {
            console.log(err)
        }
    })
}
// 下载文件并压缩
function zipFiles(zipName, files) {
    return new Promise((resolve) => {
        try {
            console.log("同步下载打包开始时间：" + new Date());
            // store.dispatch('trials/setUnLock', true)
            files = formatFiles(files)
            // 创建压缩文件输出流  
            const zipFileOutputStream = streamSaver.createWriteStream(zipName);
            // 创建下载文件流  
            const fileIterator = files.values();
            const readableZipStream = new ZIP({
                async pull(ctrl) {
                    const fileInfo = fileIterator.next();
                    if (fileInfo.done) {//迭代终止  
                        ctrl.close();
                    } else {
                        let { name, url } = fileInfo.value;
                        url = decodeUtf8(url);
                        return fetch(url).then(res => {
                            ctrl.enqueue({
                                name,
                                stream: () => res.body
                            });
                        })
                    }
                }
            });
            if (window.WritableStream && readableZipStream.pipeTo) {
                // 开始下载  
                readableZipStream
                    .pipeTo(zipFileOutputStream)
                    .then(() => {
                        console.log("同步下载打包结束时间：" + new Date());
                        // store.dispatch('trials/setUnLock', false)
                        resolve(true)
                    }).catch(err => {
                        console.log(err);
                        resolve(false)
                    });
            } else {
                resolve(false)
            }
        } catch (err) {
            console.log(err);
            resolve(false)
        }
    })

}
// 下载文件并修改名称
async function updateFile(file, name) {
    return new Promise(async resolve => {
        try {
            // store.dispatch('trials/setUnLock', true)
            const fileOutputStream = streamSaver.createWriteStream(name);
            file = decodeUtf8(file);
            let res = await fetch(file);
            res.body.pipeTo(fileOutputStream).then(() => {
                // store.dispatch('trials/setUnLock', true)
                resolve(true)
            }).catch(err => {
                console.log(err)
                resolve(false)
            });
        } catch (err) {
            console.log(err)
            resolve(false)
        }
    })
}
//  同名文件修改名称
function formatFiles(files) {
    let fileObj = {};
    files.forEach(file => {
        let arr = Object.keys(fileObj);
        if (!~arr.indexOf(file.name)) {
            fileObj[file.name] = 1;
        } else {
            let name = file.name;
            file.name = name.split(".")[0] + `(${fileObj[name]})` + name
                .substring(name.lastIndexOf('.'))
                .toLocaleLowerCase()
            fileObj[name]++;
        }
    })
    return files;
}
function decodeUtf8(bytes) {
    let str = bytes.split('?');
    let str2 = str[0].split('/');
    let name = str2[str2.length - 1];
    name = encodeURIComponent(name);
    str.shift();
    str2.pop();
    return str2.join("/") + '/' + name;
}
export async function downLoadFile(file, name, type = 'file', callback) {
    if (type === 'zip') return await zipFilesJsZip(name, file, {}, callback);
    return await updateFile(file, name)

}