"use strict";

const fs = require('fs');
const readChunk = require('read-chunk');
const fileType = require('file-type');
const logger = console;
const UtilUploads = require('../../shared/utils/UtilUploads');

/**
 * 4100 is the required number of bytes for file-type to work. see usages in PlainDirectoryProvider and UploadFileController
 */
const FILE_TYPE_SAMPLE_LENGTH = 4100;

function _base64ToBuffer(data) {
	var base64Str = ";base64,";
	var index = data.indexOf(base64Str);
	if (index !== -1) {
		data = data.substring(index + base64Str.length);
	}

	return (index !== -1 ? Buffer.from(data, 'base64') : data);
};

function deleteFiles(filePath, cb) {
	if (filePath) {
		fs.unlink(filePath, cb);
	}
};

function saveFile(filePath, file, callback) {
    var tmpPath = file.path;
    fs.rename(tmpPath, filePath, function (err) {
        if (err) throw err;
        // delete the temporary file
        fs.unlink(tmpPath, function () {
            if (err) throw err;
            callback(err);
        });
    });
}

function saveBufferFile(filePath, buffer, callback) {
    if (callback != null) {
        fs.writeFile(filePath, buffer, callback);
    } else {
        fs.writeFileSync(filePath, buffer);
    }
}

function existsAndWritable(path, cb){
    var rMode = fs.constants ? fs.constants.R_OK : fs.R_OK;
    var wMode = fs.constants ? fs.constants.W_OK : fs.W_OK;

    if(!cb){
        return new Promise((resolve, reject) => {
            fs.access(path, rMode | wMode, (err) => { //eslint-disable-line no-bitwise
                if(err){
                    reject(err);
                }else{
                    resolve();
                }
            }); //eslint-disable-line no-bitwise
        });
    }else{
        fs.access(path, rMode | wMode, cb); //eslint-disable-line no-bitwise
    }
}

function pathFileType(filePath, cb){

    readChunk(filePath, 0, FILE_TYPE_SAMPLE_LENGTH).then(function(chunkBuffer){

        if(!chunkBuffer){

            cb(new Error("ReadChunk error: unable to fetch chunk on " + filePath));
        }else{

            cb(null, bufferFileType(chunkBuffer));
        }

    });
}

function bufferFileType(buffer){

    //if contents exceed the sample length then fetch a chunk
    if(buffer.length > FILE_TYPE_SAMPLE_LENGTH){
        var chunk = Buffer.alloc(FILE_TYPE_SAMPLE_LENGTH); //file-type needs a 4100-byte chunk as sample
        buffer.copy(chunk, 0, 0, FILE_TYPE_SAMPLE_LENGTH);
        buffer = chunk;
    }

    return fileType(buffer); //returns object like  {ext: 'png', mime: 'image/png'}; returns null/undefined on error
}

module.exports = {
	_base64ToBuffer: _base64ToBuffer,
	deleteFiles: deleteFiles,
    saveFile: saveFile,
    saveBufferFile,
	existsAndWritable : existsAndWritable,
    whiteListed: UtilUploads.whiteListed,

    //For reading file type based on a chunk of its contents:
    FILE_TYPE_SAMPLE_LENGTH : FILE_TYPE_SAMPLE_LENGTH,
    pathFileType: pathFileType,
    bufferFileType: bufferFileType
};
