<commit_before>Project = require('../../models/Project').Project
Errors = require "../../errors"
_ = require('underscore')
logger = require('logger-sharelatex')
async = require('async')

module.exports =
	findElement: (options, callback = (err, element, path, parentFolder)->)->
		{project, project_id, element_id, type} = options
		elementType = sanitizeTypeOfElement type

		count = 0
		endOfBranch = ->
			if --count == 0
				logger.warn "element #{element_id} could not be found for project #{project_id || project._id}"
				return callback(new Errors.NotFoundError("entity not found"))

		search = (searchFolder, path)->
			count++
			element = _.find searchFolder[elementType], (el)-> el?._id+'' == element_id+'' #need to ToString both id's for robustness
			if !element? && searchFolder.folders? && searchFolder.folders.length != 0
				_.each searchFolder.folders, (folder, index)->
					newPath = {}
					newPath[key] = value for own key,value of path #make a value copy of the string
					newPath.fileSystem += "/#{folder.name}"
					newPath.mongo += ".folders.#{index}"
					search folder, newPath
				endOfBranch()
				return
			else if element?
				elementPlaceInArray = getIndexOf(searchFolder[elementType], element_id)
				path.fileSystem += "/#{element.name}"
				path.mongo +=".#{elementType}.#{elementPlaceInArray}"
				callback(null, element, path, searchFolder)
			else if !element?
				return endOfBranch()

		path = {fileSystem:'',mongo:'rootFolder.0'}

		startSearch = (project)->
			if element_id+'' == project.rootFolder[0]._id+''
				callback(null, project.rootFolder[0], path, null)
			else
				search project.rootFolder[0], path

		if project?
			startSearch(project)
		else
			Project.findById project_id, (err, project)->
				return callback(err) if err?
				if !project?
					return callback(new Errors.NotFoundError("project not found"))
				startSearch project

	findRootDoc : (opts, callback)->
		getRootDoc = (project)=>
			@findElement {project:project, element_id:project.rootDoc_id, type:"docs"}, callback
		{project, project_id} = opts
		if project?
			getRootDoc project
		else
			Project.findById project_id, (err, project)->
				getRootDoc project

	findElementByPath: (project_or_id, needlePath, callback = (err, foundEntity)->)->

		getParentFolder = (haystackFolder, foldersList, level, cb)->
			if foldersList.length == 0
				return cb null, haystackFolder
			needleFolderName = foldersList[level]
			found = false
			for folder in haystackFolder.folders
				if folder.name.toLowerCase() == needleFolderName.toLowerCase()
					found = true
					if level == foldersList.length-1
						return cb null, folder
					else
						return getParentFolder(folder, foldersList, level+1, cb)
			if !found
				cb("not found project_or_id: #{project_or_id} search path: #{needlePath}, folder #{foldersList[level]} could not be found")

		getEntity = (folder, entityName, cb)->
			if !entityName?
				return cb null, folder
			enteties = _.union folder.fileRefs, folder.docs, folder.folders
			result = _.find enteties, (entity)->
				entity?.name.toLowerCase() == entityName.toLowerCase()
			if result?
				cb null, result
			else
				cb("not found project_or_id: #{project_or_id} search path: #{needlePath}, entity #{entityName} could not be found")


		Project.getProject project_or_id, "", (err, project)->
			if err? or !project?
				return callback("project could not be found for finding a element #{project_or_id}")
			if needlePath == '' || needlePath == '/'<commit_msg>broken a err and null check into 2 lines<commit_after>Project = require('../../models/Project').Project
Errors = require "../../errors"
_ = require('underscore')
logger = require('logger-sharelatex')
async = require('async')

module.exports =
	findElement: (options, callback = (err, element, path, parentFolder)->)->
		{project, project_id, element_id, type} = options
		elementType = sanitizeTypeOfElement type

		count = 0
		endOfBranch = ->
			if --count == 0
				logger.warn "element #{element_id} could not be found for project #{project_id || project._id}"
				return callback(new Errors.NotFoundError("entity not found"))

		search = (searchFolder, path)->
			count++
			element = _.find searchFolder[elementType], (el)-> el?._id+'' == element_id+'' #need to ToString both id's for robustness
			if !element? && searchFolder.folders? && searchFolder.folders.length != 0
				_.each searchFolder.folders, (folder, index)->
					newPath = {}
					newPath[key] = value for own key,value of path #make a value copy of the string
					newPath.fileSystem += "/#{folder.name}"
					newPath.mongo += ".folders.#{index}"
					search folder, newPath
				endOfBranch()
				return
			else if element?
				elementPlaceInArray = getIndexOf(searchFolder[elementType], element_id)
				path.fileSystem += "/#{element.name}"
				path.mongo +=".#{elementType}.#{elementPlaceInArray}"
				callback(null, element, path, searchFolder)
			else if !element?
				return endOfBranch()

		path = {fileSystem:'',mongo:'rootFolder.0'}

		startSearch = (project)->
			if element_id+'' == project.rootFolder[0]._id+''
				callback(null, project.rootFolder[0], path, null)
			else
				search project.rootFolder[0], path

		if project?
			startSearch(project)
		else
			Project.findById project_id, (err, project)->
				return callback(err) if err?
				if !project?
					return callback(new Errors.NotFoundError("project not found"))
				startSearch project

	findRootDoc : (opts, callback)->
		getRootDoc = (project)=>
			@findElement {project:project, element_id:project.rootDoc_id, type:"docs"}, callback
		{project, project_id} = opts
		if project?
			getRootDoc project
		else
			Project.findById project_id, (err, project)->
				getRootDoc project

	findElementByPath: (project_or_id, needlePath, callback = (err, foundEntity)->)->

		getParentFolder = (haystackFolder, foldersList, level, cb)->
			if foldersList.length == 0
				return cb null, haystackFolder
			needleFolderName = foldersList[level]
			found = false
			for folder in haystackFolder.folders
				if folder.name.toLowerCase() == needleFolderName.toLowerCase()
					found = true
					if level == foldersList.length-1
						return cb null, folder
					else
						return getParentFolder(folder, foldersList, level+1, cb)
			if !found
				cb("not found project_or_id: #{project_or_id} search path: #{needlePath}, folder #{foldersList[level]} could not be found")

		getEntity = (folder, entityName, cb)->
			if !entityName?
				return cb null, folder
			enteties = _.union folder.fileRefs, folder.docs, folder.folders
			result = _.find enteties, (entity)->
				entity?.name.toLowerCase() == entityName.toLowerCase()
			if result?
				cb null, result
			else
				cb("not found project_or_id: #{project_or_id} search path: #{needlePath}, entity #{entityName} could not be found")


		Project.getProject project_or_id, "", (err, project)->
			if err?
				logger.err err:err, project_or_id:project_or_id, "error getting project for finding element"
				return callback(err)
			if !project?
				return callback("project could not be found for finding a element #{project_or_id}")
			if needlePath == '' || needlePath == '/'
{'fraction_non_alphanumeric': 0.1295676429567643, 'fraction_numerical': 0.0029288702928870294, 'mean_word_length': 3.96606648199446, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2013647', 'n_tokens_mistral': 2547, 'n_tokens_neox': 2152, 'n_words': 615}