class CreateFunctionCmd extends BackgroundCommand {

	private boolean createFunction(TaskMonitor monitor, String funcName,
			CodeBlockModel functionModel, Namespace nameSpace, Address entry, AddressSetView body,
			SourceType nameSource) throws DuplicateNameException, InvalidInputException,
			OverlappingFunctionException, CancelledException {

		FunctionManager functionMgr = program.getFunctionManager();

		// if the entry point is unknown, and just have a location in the body
		//    try to find the entry point (must wander into an existing function
		if (this.findEntryPoint) {
			// if we are already in a function, then no need to find the entry
			Function functionContaining = functionMgr.getFunctionContaining(entry);
			if (functionContaining != null) {
				// if we are not recreating the function,
				//  then don't continue because there is already a function here.
				if (!recreateFunction) {
					long bodySize = functionContaining.getBody().getNumAddresses();
					if (bodySize != 1) {
						return false;
					}
				}

				// if the function containing this entry does not start at this address
				if (!functionContaining.getEntryPoint().equals(entry)) {
					entry = findFunctionEntry(entry);
				}
			}
			if (entry == null) {
				return false;
			}
			if (origBody != null && !origBody.isEmpty()) {
				Function func = program.getFunctionManager().getFunctionContaining(entry);
				if (func == null) {
					return false;
				}
				try {
					func.setBody(origBody); // trigger analysis
					return true;
				}
				catch (OverlappingFunctionException e) {
					// don't care about overlapping functions
				}
			}
			if (fixupFunctionBody(program, program.getListing().getInstructionAt(entry), monitor)) {
				return true;
			}
		}

		Function existingFunction = functionMgr.getFunctionAt(entry);

		// if there is an existing function handle necessary changes
		if (existingFunction != null) {
			return handleExistingFunction(monitor, entry, existingFunction);
		}

		// if the body is undefined, figure it out
		// get the function body JUST by following flow
		body = (body == null ? getFunctionBody(program, entry, false, monitor) : body);

		// subtract out any existing functions that overlap the body
		AddressSetView oldbody = body;
		body = removeExistingFunctionsFromBody(entry, body, monitor);
		if (body == null) {
			return false;
		}

		Map<Function, AddressSetView> bodyChangeMap = new HashMap<>();
		// If I ain't got nobody left after extracting overlapping functions
		if (body.isEmpty()) {
			// try subtracting this body from existing functions
			//   need to compute a bodyChangeMap if affecting other functions
			//   in case creation of this function fails
			body = subtractBodyFromExisting(entry, oldbody, bodyChangeMap, monitor);
		}

		return createFunction(nameSpace, funcName, entry, body, nameSource, bodyChangeMap, monitor);
	}

	public  CreateFunctionCmd(String name, AddressSetView entries, AddressSetView body,
			SourceType source, boolean findEntryPoint, boolean recreateFunction);
	public  CreateFunctionCmd(String name, Address entry, AddressSetView body, SourceType source,
			boolean findEntryPoint, boolean recreateFunction);
	public  CreateFunctionCmd(AddressSetView entries, boolean findEntryPoint);
	public  CreateFunctionCmd(AddressSetView entries);
	public  CreateFunctionCmd(AddressSetView entries, SourceType source);
	public  CreateFunctionCmd(String name, Address entry, AddressSetView body, SourceType source);
	  CreateFunctionCmd(Address entry, List<Address> referringThunkAddresses);
	public  CreateFunctionCmd(Address entry);
	public  CreateFunctionCmd(Address entry, boolean findEntryPoint);

}