var fs = require('fs')
var moment = require('moment')
module.exports = function(s,config,lang,app,io){
    const getFileBinDirectory = function(monitor){
        return s.dir.fileBin + monitor.ke + '/' + monitor.mid + '/'
    }
    const getFileBinEntry = (options) => {
        return new Promise((resolve, reject) => {
            s.knexQuery({
                action: "select",
                columns: "*",
                table: "Files",
                where: options
            },(err,rows) => {
                if(rows[0]){
                    resolve(rows[0])
                }else{
                    resolve()
                }
            })
        })
    }
    const getFileBinBuffer = (file) => {
        const filePath = getFileBinPath(file);
        return fs.promises.readFile(filePath)
    }
    const getFileBinPath = (file) => {
        return getFileBinDirectory(file) + file.name;
    }
    const getFileBinEntries = (options) => {
        return new Promise((resolve, reject) => {
            s.knexQuery({
                action: "select",
                columns: "*",
                table: "Files",
                where: options
            },(err,rows) => {
                if(rows){
                    resolve(rows)
                }else{
                    resolve([])
                }
            })
        })
    }
    const updateFileBinEntry = (options) => {
        return new Promise((resolve, reject) => {
            const groupKey = options.ke
            const monitorId = options.mid
            const filename = options.name
            const update = options.update
            if(!filename){
                resolve('No Filename')
                return
            }
            if(!update){
                resolve('No Update Options')
                return
            }
            s.knexQuery({
                action: "select",
                columns: "size",
                table: "Files",
                where: {
                    ke: groupKey,
                    mid: monitorId,
                    name: filename,
                }
            },(err,rows) => {
                if(rows[0]){
                    const fileSize = rows[0].size
                    s.knexQuery({
                        action: "update",
                        table: "Files",
                        where: {
                            ke: groupKey,
                            mid: monitorId,
                            name: filename,
                        },
                        update: update
                    },(err) => {
                        resolve()
                        if(update.size){
                            s.setDiskUsedForGroup(groupKey,-(fileSize/1048576),'fileBin')
                            s.setDiskUsedForGroup(groupKey,(update.size/1048576),'fileBin')
                            s.purgeDiskForGroup(groupKey)
                        }
                    })
                }else{
                    resolve()
                }
            })
        })
    }
    const deleteFileBinEntry = (options) => {
        return new Promise((resolve, reject) => {
            const groupKey = options.ke
            const monitorId = options.mid
            const filename = options.name
            const whereQuery = {
                ke: groupKey,
                mid: monitorId,
                name: filename,
            }
            if(!filename){
                resolve('No Filename')
                return
            }
            const deleteRow = (fileSize) => {
                s.knexQuery({
                    action: "delete",
                    table: "Files",
                    where: whereQuery
                },(err,r) => {
                    resolve()
                    s.file('delete',getFileBinDirectory(whereQuery) + filename)
                    s.setDiskUsedForGroup(groupKey,-(fileSize/1048576),'fileBin')
                    s.purgeDiskForGroup(groupKey)
                })
            }
            if(options.size){
                deleteRow(options.size)
            }else{
                s.knexQuery({
                    action: "select",
                    columns: "size",
                    table: "Files",
                    where: whereQuery
                },(err,rows) => {
                    if(rows[0]){
                        const fileSize = rows[0].size
                        deleteRow(fileSize)
                    }else{
                        resolve()
                    }
                })
            }
        })
    }
    const insertFileBinEntry = (options) => {
        return new Promise((resolve, reject) => {
            const groupKey = options.ke
            const monitorId = options.mid
            const filename = options.name
            if(!filename){
                resolve('No Filename')
                return
            }
            const monitorFileBinDirectory = getFileBinDirectory({ke: groupKey,mid: monitorId,})
            const fileSize = options.size || fs.lstatSync(monitorFileBinDirectory + filename).size
            const details = options.details instanceof Object ? JSON.stringify(options.details) : options.details
            const status = options.status || 0
            const time = options.time || new Date()
            s.knexQuery({
                action: "insert",
                table: "Files",
                insert: {
                    ke: groupKey,
                    mid: monitorId,
                    name: filename,
                    size: fileSize,
                    details: details,
                    status: status,
                    time: time,
                }
            },(err) => {
                resolve()
                s.setDiskUsedForGroup(groupKey,(fileSize/1048576),'fileBin')
                s.purgeDiskForGroup(groupKey)
            })
        })
    }
    function archiveFileBinEntry(file,unarchive){
        return new Promise((resolve) => {
            s.knexQuery({
                action: "update",
                table: 'Files',
                update: {
                    archive: unarchive ? '0' : 1
                },
                where: {
                    ke: file.ke,
                    mid: file.mid,
                    name: file.name,
                }
            },function(err){
                resolve({
                    ok: !err,
                    err: err,
                    archived: !unarchive
                })
            })
        })
    }
    s.getFileBinDirectory = getFileBinDirectory
    s.getFileBinEntry = getFileBinEntry
    s.getFileBinBuffer = getFileBinBuffer
    s.getFileBinPath = getFileBinPath
    s.insertFileBinEntry = insertFileBinEntry
    s.updateFileBinEntry = updateFileBinEntry
    s.deleteFileBinEntry = deleteFileBinEntry
    s.archiveFileBinEntry = archiveFileBinEntry
    /**
    * API : Get fileBin file rows
     */
    app.get([config.webPaths.apiPrefix+':auth/fileBin/:ke',config.webPaths.apiPrefix+':auth/fileBin/:ke/:id'],async (req,res) => {
        s.auth(req.params,(user) => {
            const userDetails = user.details
            const monitorId = req.params.id
            const groupKey = req.params.ke
            const hasRestrictions = userDetails.sub && userDetails.allmonitors !== '1';
            s.sqlQueryBetweenTimesWithPermissions({
                table: 'Files',
                user: user,
                groupKey: req.params.ke,
                monitorId: req.params.id,
                startTime: req.query.start,
                endTime: req.query.end,
                startTimeOperator: req.query.startOperator,
                endTimeOperator: req.query.endOperator,
                limit: req.query.limit,
                archived: req.query.archived,
                endIsStartTo: true,
                noFormat: true,
                noCount: true,
                preliminaryValidationFailed: (
                    user.permissions.get_monitors === "0"
                )
            },(response) => {
                response.forEach(function(v){
                    v.details = s.parseJSON(v.details)
                    v.href = '/'+req.params.auth+'/fileBin/'+req.params.ke+'/'+req.params.id+'/'+v.name;
                })
                s.closeJsonResponse(res,{
                    ok: true,
                    files: response
                })
            })
        },res,req);
    });
    /**
    * API : Get fileBin file
     */
    app.get(config.webPaths.apiPrefix+':auth/fileBin/:ke/:id/:file', async (req,res) => {
        s.auth(req.params,function(user){
            var failed = function(){
                res.end(user.lang['File Not Found'])
            }
            const groupKey = req.params.ke
            const monitorId = req.params.id
            const {
                monitorPermissions,
                monitorRestrictions,
            } = s.getMonitorsPermitted(user.details,monitorId)
            const {
                isRestricted,
                isRestrictedApiKey,
                apiKeyPermissions,
            } = s.checkPermission(user)
            if(
                isRestrictedApiKey && apiKeyPermissions.watch_videos_disallowed ||
                isRestricted && !monitorPermissions[`${monitorId}_video_view`]
            ){
                s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
                return
            }
            s.knexQuery({
                action: "select",
                columns: "*",
                table: "Files",
                where: [
                    ['ke','=',groupKey],
                    ['mid','=',req.params.id],
                    ['name','=',req.params.file],
                    monitorRestrictions
                ]
            },(err,r) => {
                if(r && r[0]){
                    r = r[0]
                    r.details = JSON.parse(r.details)
                    const filename = req.params.file
                    const filePath = s.dir.fileBin + req.params.ke + '/' + req.params.id + (r.details.year && r.details.month && r.details.day ? '/' + r.details.year + '/' + r.details.month + '/' + r.details.day : '') + '/' + filename;
                    fs.stat(filePath,function(err,stats){
                        if(!err){
                            if(filename.endsWith('.mp4')){
                                s.streamMp4FileOverHttp(filePath,req,res,!!req.query.pureStream)
                            }else{
                                res.on('finish',function(){res.end()})
                                fs.createReadStream(filePath).pipe(res)
                            }
                        }else{
                            failed()
                        }
                    })
                }else{
                    failed()
                }
            })
        },res,req);
    });
    /**
    * API : Modify fileBin File
     */
    app.get(config.webPaths.apiPrefix+':auth/fileBin/:ke/:id/:file/:mode', function (req,res){
        let response = { ok: false };
        res.setHeader('Content-Type', 'application/json');
        s.auth(req.params,function(user){
            const monitorId = req.params.id
            const groupKey = req.params.ke
            const filename = req.params.file
            const {
                monitorPermissions,
                monitorRestrictions,
            } = s.getMonitorsPermitted(user.details,monitorId)
            const {
                isRestricted,
                isRestrictedApiKey,
                apiKeyPermissions,
            } = s.checkPermission(user);
            if(
                isRestrictedApiKey && apiKeyPermissions.delete_videos_disallowed ||
                isRestricted && !monitorPermissions[`${monitorId}_video_delete`]
            ){
                s.closeJsonResponse(res,{ok: false, msg: lang['Not Authorized']});
                return
            }
            s.knexQuery({
                action: "select",
                columns: "*",
                table: 'Files',
                where: [
                    ['ke','=',groupKey],
                    ['mid','=',monitorId],
                    ['name','=',filename]
                ],
                limit: 1
            },async (err,r) => {
                if(r && r[0]){
                    const file = r[0];
                    var details = s.parseJSON(r.details) || {}
                    switch(req.params.mode){
                        case'archive':
                            response.ok = true
                            const unarchive = s.getPostData(req,'unarchive') == '1';
                            const archiveResponse = await archiveFileBinEntry(file,unarchive)
                            response.ok = archiveResponse.ok
                            response.archived = archiveResponse.archived
                        break;
                        case'delete':
                            response.ok = true;
                            await deleteFileBinEntry(file)
                        break;
                        default:
                            response.msg = user.lang.modifyVideoText1;
                        break;
                    }
                }else{
                    response.msg = user.lang['No such file'];
                }
                s.closeJsonResponse(res,response);
            })
        },res,req);
    })
}
