
/*=============================================================================================
	author:ZhaoJun
	version:1.2
	email:2732810281@qq.com
=============================================================================================*/


//严格模式
/*-------------------------------------------------------------------------------------------*/	
    'use strict';
/*-------------------------------------------------------------------------------------------*/
    
// 复用的操作
/*-------------------------------------------------------------------------------------------*/	
	class media
  	{
		static async mongo(request, response,id)
		{
			const mongodb=require('mongodb')
			const ObjectID = require('mongodb').ObjectID
			var db = $DbMongo.$con['main'].db('fs')
			
			const bucket = new mongodb.GridFSBucket(db);
			
			id=new ObjectID(id);

			let data=await db.collection('fs.files').findOne({_id:id})
			if(!data)
			{
				media.sendResponse(response, 404, null, null);
				return null;
			}


			var responseHeaders = {};
			var rangeRequest = media.readRangeHeader(request.headers['range'], data.length);

			if (rangeRequest == null) 
			{
				responseHeaders['Content-Type'] = "application/octet-stream";
				responseHeaders['Content-Length'] = stat.size; // File size.
				responseHeaders['Accept-Ranges'] = 'bytes';
				media.sendResponse(response, 200, responseHeaders, bucket.openDownloadStream(id));
				return;
			}
		
			var start = rangeRequest.Start;
			var end = rangeRequest.End;
		
			if (start >= data.length || end >= data.length) 
			{
				responseHeaders['Content-Range'] = 'bytes */' + data.length; 
				media.sendResponse(response, 416, responseHeaders, null);
				return null;
			}
		
			responseHeaders['Content-Range'] = 'bytes ' + start + '-' + end + '/' + data.length;
			responseHeaders['Content-Length'] = start == end ? 0 : (end - start + 1);
			responseHeaders['Content-Type'] = "application/octet-stream";
			responseHeaders['Accept-Ranges'] = 'bytes';
			responseHeaders['Cache-Control'] = 'no-cache';
		
			media.sendResponse(response, 206, responseHeaders, bucket.openDownloadStream(id,{ start: start, end: end }));
		}

		static custom(request, response,filename)
		{
			var fs=require('fs');
			if (!fs.existsSync(filename)) 
			{
				media.sendResponse(response, 404, null, null);
				return null;
			}
		
			var responseHeaders = {};
			var stat = fs.statSync(filename);
			var rangeRequest = media.readRangeHeader(request.headers['range'], stat.size);
		
			if (rangeRequest == null) 
			{
				responseHeaders['Content-Type'] = "application/octet-stream";
				responseHeaders['Content-Length'] = stat.size; // File size.
				responseHeaders['Accept-Ranges'] = 'bytes';
		
				media.sendResponse(response, 200, responseHeaders, fs.createReadStream(filename));
				return;
			}
		
			var start = rangeRequest.Start;
			var end = rangeRequest.End;
		
			if (start >= stat.size || end >= stat.size) 
			{
				responseHeaders['Content-Range'] = 'bytes */' + stat.size; 
				media.sendResponse(response, 416, responseHeaders, null);
				return null;
			}
		
			responseHeaders['Content-Range'] = 'bytes ' + start + '-' + end + '/' + stat.size;
			responseHeaders['Content-Length'] = start == end ? 0 : (end - start + 1);
			responseHeaders['Content-Type'] = "application/octet-stream";
			responseHeaders['Accept-Ranges'] = 'bytes';
			responseHeaders['Cache-Control'] = 'no-cache';
		
			media.sendResponse(response, 206, responseHeaders, fs.createReadStream(filename, { start: start, end: end }));
		}

		static sendResponse(response, responseStatus, responseHeaders, readable) 
		{
			response.writeHead(responseStatus, responseHeaders);
			
			if (readable == null)
			{
				response.end();
			}
			else
			{
				readable.pipe(response);
			}
		}
			
		
		static readRangeHeader(range, totalLength) 
		{
			if (range == null || range.length == 0) return null;
			
			var array = range.split(/bytes=([0-9]*)-([0-9]*)/);
			var start = parseInt(array[1]);
			var end = parseInt(array[2]);
			var result = {
				Start: isNaN(start) ? 0 : start,
				End: isNaN(end) ? (totalLength - 1) : end
			};
			
			if (!isNaN(start) && isNaN(end)) 
			{
				result.Start = start;
				result.End = totalLength - 1;
			}
			
			if (isNaN(start) && !isNaN(end)) 
			{
				result.Start = totalLength - end;
				result.End = totalLength - 1;
			}
		  
			return result;
		}
  }
/*-------------------------------------------------------------------------------------------*/    
module.exports=media;