//文件类型，对应内容模块Blob目录
const CONTENT_TYPES = {
    'image': ['JPG', 'JPEG', 'PNG', 'GIF', 'SVG'],
    'video': ['AVI', 'MP4', 'WEBM'],
    'doc': ['PPT', 'PPTX', 'DOC', 'DOCX', 'PDF', 'XLS', 'XLSX', 'CSV'],
    'res': ['HTE', 'HETX'],
    'audio': ['MP3', 'WAV', 'OGG']
}

const { BlobServiceClient, BlobClient } = require("@azure/storage-blob")

//获取文件后缀和类型
function getExAndType(fileName) {
    let ex = fileName.substring(fileName.lastIndexOf('.') + 1)
    let type = 'other'
    ex = ex.toUpperCase()
    for (let key in CONTENT_TYPES) {
        if (CONTENT_TYPES[key].indexOf(ex) != -1) {
            type = key
            break
        }
    }
    return {
        ex, type
    }
}

export default class BlobTool {

    /**
     * 初始化Blob,需要先调用授权API
     * @param {string} blobUrl blob地址
     * @param {string} container 容器名称
     * @param {string} sasString 授权
     * */
    constructor(blobUrl, container, sasString) {
        this.initBlob(blobUrl, container, sasString)
    }
    /**
     * 初始化Blob,需要先调用授权API
     * @param {string} blobUrl blob地址
     * @param {string} container 容器名称
     * @param {string} sasString 授权
     * @param {string} scope 学校(school)/个人(private) 计算空间大小
     * */
    initBlob(blobUrl, container, sasString) {
        if (blobUrl && container && sasString) {
            //初始化containerClient
            this.blobService = new BlobServiceClient(blobUrl + '?' +sasString)
            let containerClient = this.blobService.getContainerClient(container)
            if (containerClient) {
                this.containerClient = containerClient
                this.container = container
                this.blobUrl = blobUrl
                this.sasString = sasString
            } else {
                throw new Error("参数错误，初始化失败")
            }
        } else {
            throw new Error("初始化参数不完整")
        }
    }

    /**
     * 获取容器信息 (授权失败，暂时不能使用)
     * @param {object}
     */
    getProperties(options) {
        return new Promise((r, j) => {
            //const blockBlobClient = this.containerClient.getBlockBlobClient('res/基础操作范例_16x9.HTE') //blob获取成功
            this.containerClient.getProperties(options).then(
                res => {
                    console.log('获取信息成功')
                    console.log(res)
                    r(res)
                },
                err => {
                    console.log('获取信息失败')
                    console.log(err)
                    j(err)
                }
            )
        })
    }

    /**
     * 上传文件方法,带回调上传进度
     * @param {any} file 文件对象
     * @param {any} path 文件夹路径
     * @param {any} option 官方可配置项
     *
     * @returns {object} {url, name,size,createTime,extension,type}
     */
    upload(file, path, option) {
        return new Promise(async (r, j) => {
            const blockBlobClient = this.containerClient.getBlockBlobClient(path + "/" + file.name)
            console.log(blockBlobClient)
            blockBlobClient.uploadBrowserData(file, option).then(
                res => {
                    let url = decodeURIComponent(res._response.request.url)
                    url = url.substring(0, url.lastIndexOf('?'))
                    let info = getExAndType(file.name)
                    this.totalSize += res._response.request.body.size
                    r({
                        url: url,
                        blob: '/' + path + "/" + file.name,
                        name: file.name,
                        size: res._response.request.body.size,
                        createTime: res.lastModified.getTime(),
                        extension: info.ex,
                        type: info.type
                    })
                },
                err => {
                    j(err)
                }
            )
        })
    }

    /**
     * 列出（查询）
     * @param {Object} option ContainerListBlobsOptions
     * eg: option.prefix = 'res' 只查res文件夹下的blob
     * @param {Object} pageInfo
     * eg: pageInfo.maxPageSize 当前请求条数
     * eg: pageInfo.continuationToken 首次请求不需要，后面需要（首次请求会返回，下次需要传入）
     *
     * @returns {object} {blobList, continuationToken}
     */
    async listBlob(option, pageInfo) {
        return new Promise(async (r, j) => {
            let page = {}
            let blobList = []
            if (pageInfo && JSON.stringify(pageInfo) != '{}') {
                page.maxPageSize = pageInfo.maxPageSize ? pageInfo.maxPageSize : 50
                if (pageInfo.continuationToken) {
                    page.continuationToken = pageInfo.continuationToken ? pageInfo.continuationToken : ''
                }
            }
            if (this.containerClient) {
                let iterator = this.containerClient.listBlobsFlat(option ? option : {}).byPage(page)
                let response = (await iterator.next()).value
                let prefixLen = response.prefix ? response.prefix.length + 1: 0
                for (const blob of response.segment.blobItems) {
                    let info = getExAndType(blob.name)
                    blobList.push(
                        {
                            url: response.serviceEndpoint + response.containerName + '/' + blob.name,
                            blob: '/' + blob.name,
                            name: blob.name.substring(prefixLen),
                            size: blob.properties.contentLength,
                            createTime: blob.properties.lastModified.getTime(),
                            extension: info.ex,
                            type: info.type
                        }
                    )
                }
                let continuationToken = response.continuationToken ? response.continuationToken : 'end'
                r({
                    blobList,
                    continuationToken
                })
            } else {
                j('containerClient 错误')
            }
        })
    }

    /**
     * 删除Blob
     * @param {string} filePath 文件url + 容器 之后的路径
     */
    deleteBlob(filePath) {
        if (filePath) {
            filePath = filePath.substring(1)
        }
        return new Promise((r, j) => {
            this.containerClient.deleteBlob(filePath).then(
                res => {
                    r(res)
                },
                err => {
                    j(err)
                }
            )

        })
    }

    /**
     * 批量删除Blob 官方API授权失败
     * @param {string} files 文件url + 容器 之后的路径
     */
    //deleteBlobBatch(files) {
    //    let blobBatchClient = this.blobService.getBlobBatchClient()
    //    return new Promise((r, j) => {
    //        let blobs = [] //BlobClient[]
    //        for (let i in files) {
    //            //files[i] = files[i].substring(0, files[i].lastIndexOf('?'))
    //            blobs.push(new BlobClient(files[i]))
    //        }
    //        console.log(files)
    //        console.log(blobs)
    //        console.log(this.containerClient.credential)
    //        blobBatchClient.deleteBlobs(blobs).then(
    //            res => {
    //                console.log('批量删除成功')
    //                console.log(res)
    //            },
    //            err => {
    //                console.log('批量删除失败')
    //                console.log(err)
    //            }
    //        )
    //    })
    //}
    /**
     * 批量删除Blob 循环操作
     * @param {string} files
     */
    deleteBlobBatch(files) {
        return new Promise((r, j) => {
            let promises = []
            for (let item of files) {
                let f = item.substring(1)
                promises.push(this.containerClient.deleteBlob(f))
            }
            Promise.all(promises).then(
                res => {
                    r(res)
                },
                err => {
                    j(err)
                }
            )
        })
    }

    /**
     * 判断文件是否存在
     * @param {string} filePath 文件路径 正确 'res/基础操作范例_16x9.HTE ' 错误 '/res/基础操作范例_16x9.HTE'
     * @param {object}
     *
     * return true/false
     */
    exists(filePath,options) {
        const blockBlobClient = this.containerClient.getBlockBlobClient(filePath)
        return new Promise((r, j) => {
            blockBlobClient.exists(options).then(
                res => {
                    r(res)
                },
                err => {
                    j(err)
                }
            )
        })
    }
    /**
     * 计算容器的空间大小
     * @param {string}
     * @param {object}
     *
     * return true/false
     */
    async getContainerSize() {
        return new Promise((r, j) => {
            this.listBlob().then(
                res => {
                    let totalSize = res.blobList.reduce((total, item) => {
                        return total + parseInt(item.size)
                    }, 0)
                    this.totalSize = totalSize
                    r(totalSize)
                },
                err => {
                    j(err)
                }
            )
        })
    }

}
