'use strict';

const { logger } = require("handlebars");
var q = require("q");
var UtilError = require('../../utils/UtilError');

var SharedConstants = require('../../../shared/constants/SharedConstants');
var AccessManager = require('../../../shared/access/AccessManager');

//Helper, private and isn't exposed. Uses the databaseService directly for looking up documents
function directFind(query, userAccountControlDocument, fileNo){

    var deferred = q.defer();

    //Uses the database service for finding docs directly. The findService.find has limitations because APIs use it.
    DBProvider.dataFindService.findByQuery(query, null).then( function succFn(results) {
        
        if (results.length === 0) {
            deferred.reject(new UtilError.NotFoundError("File not found: " + fileNo));
        } else {
            var finalResult = [];
            var hasPermission = false;
            //manually check if deleted because it's difficult design a query that works for it on mongo
            //mongo has {$ne: false} notation
            results.forEach(function (each) {
                var deleted = each.systemHeader.deleted;
                if (!deleted || deleted === false || deleted === 'false') {
        
                    var checkPermission = AccessManager.hasPermission(each, userAccountControlDocument
                        , SharedConstants.OPERATION_TYPE_READ);
                    if (checkPermission) {
                        finalResult.push(each);
                        hasPermission = true;
                    }
                    
                }
            });
            deferred.resolve({ finalResult, hasPermission });
        }
    }, function(err){
        deferred.reject(err);
    }
    );

    return deferred.promise;
}

function fetchFileReferenceDocumentQuery(fileUploaderField, fileNo){

    let c1 = {};
    c1[fileUploaderField + ".fileNo"] = fileNo;

    let c2 = {};
    c2[fileUploaderField + ".serverAssignedFileNo"] = fileNo;

    let query = {
        "$and":[
            {
                "systemHeader.systemType": SharedConstants.SYSTEM_TYPE_FILE_REFERENCE,
                "$or":[c1, c2]
            },
            {
                "systemHeader.currentVersion":true
            },
            {
                "$or":[
                    {
                        "systemHeader.systemType":{"$ne":"accountSecurity"}
                    }
                ]
            }
        ]
    };


    return query;
}

const fetchFileReferenceDocument = (fileUploaderField, fileNo, userId, options) => {
    var deferred = q.defer();
    options = options ? options : {};
    const query = fetchFileReferenceDocumentQuery(fileUploaderField, fileNo);

    const AccountService = require("../dataServices/AccountService");
    AccountService.getAccountControlDocument(userId).then(
        function successFunc(userAccountControlDocument){

            const find = directFind(query, userAccountControlDocument, fileNo);
            find.then(
                function successFn(docs) {
                    if(docs.hasPermission) {
                        deferred.resolve(docs.finalResult);
                    } else {
                        deferred.reject(new UtilError.NoPermissionError());
                    }    
                },
                function errFn(err) {
                    deferred.reject(err);
                }
            );

        }, function errorFunc(err) {
            deferred.reject(errorMessage(SharedConstants.ERROR_TYPE_INTERNAL,
                "Couldn't get user in findOne: " + JSON.stringify(userId) + ". Error: " + err));
        } 
    );
    return deferred.promise;
};

module.exports = {
    fetchFileReferenceDocument
};
