const fs=require("fs-extra"),path=require("path"),http=require("http"),https=require("https"),appConfig=require("./config"),filenameUtils=require("./filename-utils"),sfxIndex=require("./sfx-index");async function _coreDownload(options,saveDir){const{file_url:file_url,display_name:display_name,file_hash:file_hash,token:token,sender:sender,progressChannel:progressChannel,logger:logger}=options,finalFilename=filenameUtils.buildSfxFilename(display_name,file_hash,file_url),localPath=path.join(saveDir,finalFilename);try{fs.ensureDirSync(saveDir)}catch(e){const errorMsg=`无法创建目录：${saveDir}`;throw logger&&logger(errorMsg),sender&&sender.send(progressChannel,{status:"error",message:errorMsg}),new Error(errorMsg)}return fs.existsSync(localPath)?(logger&&logger(`[Main] 文件已存在，跳过下载：${localPath}`),sender&&sender.send(progressChannel,{status:"done",percent:100,message:"使用缓存"}),{path:localPath,filename:finalFilename,cached:!0}):(logger&&logger(`[Main] 开始下载：${file_url}`),new Promise((resolve,reject)=>{const protocol=file_url.startsWith("https")?https:http,reqOptions={headers:{"User-Agent":"BigBear-Client/1.0"}};token&&token.trim()&&(reqOptions.headers.Authorization=`Bearer ${token.trim()}`);const request=protocol.get(file_url,reqOptions,response=>{if(301===response.statusCode||302===response.statusCode){const redirectUrl=response.headers.location;if(redirectUrl)return logger&&logger(`[Main] 检测到重定向：${redirectUrl}`),void _coreDownload({...options,file_url:redirectUrl},saveDir).then(resolve).catch(reject)}if(200!==response.statusCode){const errorMsg=`HTTP ${response.statusCode}`;return sender&&sender.send(progressChannel,{status:"error",message:errorMsg}),void reject(new Error(`下载失败，状态码：${response.statusCode}`))}const totalBytes=parseInt(response.headers["content-length"],10)||0;let downloadedBytes=0;const fileStream=fs.createWriteStream(localPath);response.on("data",chunk=>{if(downloadedBytes+=chunk.length,totalBytes>0&&sender){const percent=(downloadedBytes/totalBytes*100).toFixed(1);sender.send(progressChannel,{status:"progress",percent:parseFloat(percent),message:`正在下载 ${percent}%`})}else sender&&sender.send(progressChannel,{status:"indeterminate",message:"正在接收数据... "})}),response.pipe(fileStream),fileStream.on("finish",()=>{fileStream.close();try{sfxIndex.addToIndex(file_hash,finalFilename)}catch(e){}sender&&sender.send(progressChannel,{status:"done",percent:100,message:"下载完成"}),resolve({path:localPath,filename:finalFilename,cached:!1})}),fileStream.on("error",err=>{fs.unlink(localPath,()=>{}),sender&&sender.send(progressChannel,{status:"error",message:err.message}),reject(err)})});request.on("error",err=>{sender&&sender.send(progressChannel,{status:"error",message:err.message}),reject(err)}),request.setTimeout(12e5,()=>{request.destroy(),sender&&sender.send(progressChannel,{status:"error",message:"下载超时"}),reject(new Error("下载超时"))})}))}function getDefaultCacheDir(){const cacheDir=path.join(appConfig.getBGXiongDataPath(),"sfx_downloads");return fs.existsSync(cacheDir)||fs.mkdirSync(cacheDir,{recursive:!0}),cacheDir}async function downloadSfx(options){return _coreDownload(options,path.join(appConfig.getBGXiongDataPath(),"sfx_downloads"))}async function downloadToDir(options,customDir){if(!customDir)throw new Error("自定义下载方法必须指定 customDir 参数");return _coreDownload(options,customDir)}async function downloadUpdate(options){const cacheDir=path.join(appConfig.getUpdatePath());return fs.existsSync(cacheDir)||fs.mkdirSync(cacheDir,{recursive:!0}),_coreDownload(options,cacheDir)}module.exports={downloadUpdate:downloadUpdate,downloadSfx:downloadSfx,downloadToDir:downloadToDir};