/*******************************************************************************
 * Copyright (c) 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/


#include "StdAfx.h"
#include "CrossfireBPManager.h"

const wchar_t* CrossfireBPManager::KEY_BREAKPOINTS = L"breakpoints";

CrossfireBPManager::CrossfireBPManager() {
	m_breakpoints = new std::map<unsigned int, CrossfireBreakpoint*>;
}

CrossfireBPManager::~CrossfireBPManager() {
	std::map<unsigned int,CrossfireBreakpoint*>::iterator iterator = m_breakpoints->begin();
	while (iterator != m_breakpoints->end()) {
		delete iterator->second;
		iterator++;
	}
	delete m_breakpoints;
}

/* IBreakpointTarget */

bool CrossfireBPManager::breakpointAttributeChanged(unsigned int handle, wchar_t* name, Value* value) {
	/* no further action required since this object just stores the breakpoint data */
	return true;
}

bool CrossfireBPManager::deleteBreakpoint(unsigned int handle) {
	std::map<unsigned int, CrossfireBreakpoint*>::iterator iterator = m_breakpoints->find(handle);
	if (iterator == m_breakpoints->end()) {
		return false;
	}

	delete iterator->second;
	m_breakpoints->erase(iterator);
	return true;
}

CrossfireBreakpoint* CrossfireBPManager::getBreakpoint(unsigned int handle) {
	std::map<unsigned int, CrossfireBreakpoint*>::iterator iterator = m_breakpoints->find(handle);
	if (iterator == m_breakpoints->end()) {
		Logger::error("CrossfireBPManager.getBreakpoint(): unknown breakpoint handle", handle);
		return NULL;
	}

	return iterator->second;
}

void CrossfireBPManager::getBreakpoints(CrossfireBreakpoint*** ___values) {
	size_t size = m_breakpoints->size();
	CrossfireBreakpoint** breakpoints = new CrossfireBreakpoint*[size + 1];

	std::map<unsigned int, CrossfireBreakpoint*>::iterator it = m_breakpoints->begin();
	int index = 0;
	while (it != m_breakpoints->end()) {
		it->second->clone(&breakpoints[index++]);
		it++;
	}
	breakpoints[index] = NULL;

	*___values = breakpoints;
}

bool CrossfireBPManager::setBreakpoint(CrossfireBreakpoint *breakpoint) {
	CrossfireLineBreakpoint* lineBp = (CrossfireLineBreakpoint*)breakpoint;
	CrossfireLineBreakpoint* copy = NULL;
	lineBp->clone((CrossfireBreakpoint**)&copy);
	unsigned int handle = lineBp->getHandle();

	/* if a breakpoint with a duplicate handle exists then replace it with the new breakpoint */
	std::map<unsigned int, CrossfireBreakpoint*>::iterator iterator = m_breakpoints->find(handle);
	if (iterator != m_breakpoints->end()) {
		delete iterator->second;
		m_breakpoints->erase(iterator);
	}

	m_breakpoints->insert(std::pair<unsigned int, CrossfireBreakpoint*>(handle, copy));
	return true;
}

/* CrossfireBPManager */

int CrossfireBPManager::commandChangeBreakpoints(Value* arguments, IBreakpointTarget** targets, Value** _responseBody, wchar_t** _message) {
	*_responseBody = NULL;

	Value* value_handles = arguments->getObjectValue(CrossfireBreakpoint::KEY_HANDLES);
	if (!value_handles || value_handles->getType() != TYPE_ARRAY) {
		*_message = _wcsdup(L"'changeBreakpoints' command does not have a valid 'handles' value");
		return CODE_INVALID_ARGUMENT;
	}

	Value* value_attributes = arguments->getObjectValue(CrossfireBreakpoint::KEY_ATTRIBUTES);
	if (!value_attributes || value_attributes->getType() != TYPE_OBJECT) {
		*_message = _wcsdup(L"'changeBreakpoints' command does not have a valid 'attributes' value");
		return CODE_INVALID_ARGUMENT;
	}

	int code = CODE_OK;
	Value** handles = NULL;
	value_handles->getArrayValues(&handles);
	int handlesIndex = 0;
	Value* value_handle = handles[handlesIndex++];
	while (value_handle) {
		if (value_handle->getType() != TYPE_NUMBER || value_handle->getNumberValue() < 1) {
			*_message = _wcsdup(L"'changeBreakpoints' command specifies an invalid handle value");
			code = CODE_INVALID_ARGUMENT;
			break;
		}

		/* ensure that the handle is valid */
		unsigned int handle = (unsigned int)value_handle->getNumberValue();
		CrossfireBreakpoint* breakpoint = getBreakpoint(handle);
		if (!breakpoint) {
			*_message = _wcsdup(L"'changeBreakpoints' command specifies an unknown breakpoint handle");
			code = CODE_COMMAND_FAILED;
			break;
		}

		/* ensure that all attributes can be applied to the current breakpoint */
		if (!breakpoint->attributesValueIsValid(value_attributes)) {
			*_message = _wcsdup(L"'changeBreakpoints' command specifies an invalid breakpoint attribute");
			code = CODE_COMMAND_FAILED;
			break;
		}

		value_handle = handles[handlesIndex++];
	}

	if (code != CODE_OK) {
		delete[] handles;
		return code;
	}

	/* the request is valid, so now perform the changes */

	handlesIndex = 0;
	value_handle = handles[handlesIndex++];
	while (value_handle) {
		unsigned int handle = (unsigned int)value_handle->getNumberValue();
		CrossfireBreakpoint* breakpoint = getBreakpoint(handle);
		breakpoint->setAttributesFromValue(value_attributes);

		/* it's valid for the breakpoint to not be set in some (or even all) of the targets */
		if (targets) {
			int targetsIndex = 0;
			IBreakpointTarget* target = targets[targetsIndex++];
			while (target != NULL) {
				CrossfireBreakpoint* breakpoint = target->getBreakpoint(handle);
				if (breakpoint) {
					breakpoint->setAttributesFromValue(value_attributes);
				}
				target = targets[targetsIndex++];
			}
		}

		value_handle = handles[handlesIndex++];
	}
	delete[] handles;

	Value* result = new Value();
	result->setType(TYPE_OBJECT);
	*_responseBody = result;
	return CODE_OK;
}

int CrossfireBPManager::commandDeleteBreakpoints(Value* arguments, IBreakpointTarget** targets, Value** _responseBody, wchar_t** _message) {
	*_responseBody = NULL;

	Value* value_handles = arguments->getObjectValue(CrossfireBreakpoint::KEY_HANDLES);
	if (!value_handles || value_handles->getType() != TYPE_ARRAY) {
		*_message = _wcsdup(L"'deleteBreakpoints' command does not have a valid 'handles' value");
		return CODE_INVALID_ARGUMENT;
	}

	Value** handles = NULL;
	value_handles->getArrayValues(&handles);
	int index = 0;
	Value* value_current = handles[index++];
	while (value_current) {
		if (value_current->getType() != TYPE_NUMBER || (unsigned int)value_current->getNumberValue() < 1) {
			*_message = _wcsdup(L"'deleteBreakpoints' command specifies an invalid handle value");
			delete[] handles;
			return CODE_INVALID_ARGUMENT;
		}

		unsigned int handle = (unsigned int)value_current->getNumberValue();

		/* look up the breakpoint in the local breakpoints table to ensure that the handle is valid */
		std::map<unsigned int, CrossfireBreakpoint*>::iterator iterator = m_breakpoints->find(handle);
		if (iterator == m_breakpoints->end()) {
			*_message = _wcsdup(L"'deleteBreakpoints' command specifies an unknown breakpoint handle");
			delete[] handles;
			return CODE_COMMAND_FAILED;
		}
		value_current = handles[index++];
	}

	/* the request is valid, so now perform the deletions */

	index = 0;
	value_current = handles[index++];
	while (value_current) {
		unsigned int handle = (unsigned int)value_current->getNumberValue();
		deleteBreakpoint(handle); /* delete from the global table */

		/*
		 * It's valid for the breakpoint to not be set in some (or even all) of the targets,
		 * so a false result value for the deleteBreakpoint() call does not indicate a problem.
		 */
		if (targets) {
			int targetsIndex = 0;
			IBreakpointTarget* current = targets[targetsIndex++];
			while (current != NULL) {
				current->deleteBreakpoint(handle);
				current = targets[targetsIndex++];
			}
		}
		value_current = handles[index++];
	}
	delete[] handles;

	Value* result = new Value();
	result->setType(TYPE_OBJECT);
	*_responseBody = result;
	return CODE_OK;
}

int CrossfireBPManager::commandGetBreakpoints(Value* arguments, IBreakpointTarget* target, Value** _responseBody, wchar_t** _message) {
	CrossfireBreakpoint** breakpoints = NULL;
	Value* value_handles = arguments->getObjectValue(CrossfireBreakpoint::KEY_HANDLES);
	if (value_handles) {
		if (value_handles->getType() != TYPE_ARRAY) {
			*_message = _wcsdup(L"'getBreakpoints' command has an invalid 'handles' value");
			return CODE_INVALID_ARGUMENT;
		}
		std::vector<CrossfireBreakpoint*> breakpointsCollection;
		Value** handles = NULL;
		value_handles->getArrayValues(&handles);
		int index = 0;
		Value* value_current = handles[index++];
		while (value_current) {
			if (value_current->getType() == TYPE_NUMBER && value_current->getNumberValue() > 0) {
				unsigned int handle = (unsigned int)value_current->getNumberValue();
				CrossfireBreakpoint* breakpoint = target->getBreakpoint(handle);
				if (breakpoint) {
					breakpointsCollection.push_back(breakpoint);
				}
			}
			value_current = handles[index++];
		}
		delete[] handles;

		int length = breakpointsCollection.size();
		breakpoints = new CrossfireBreakpoint*[length + 1];
		for (int i = 0; i < length; i++) {
			breakpoints[i] = breakpointsCollection.at(i);
		}
		breakpoints[length] = NULL;
	} else {
		target->getBreakpoints(&breakpoints);
	}

	Value breakpointsArray;
	breakpointsArray.setType(TYPE_ARRAY);
	int index = 0;
	while (breakpoints[index]) {
		CrossfireBreakpoint* current = breakpoints[index];
		Value* value_breakpoint = NULL;
		if (current->toValueObject(&value_breakpoint)) {
			breakpointsArray.addArrayValue(value_breakpoint);
			delete value_breakpoint;
		}
		delete current;
		index++;
	}
	delete[] breakpoints;

	Value* result = new Value();
	result->addObjectValue(KEY_BREAKPOINTS, &breakpointsArray);
	*_responseBody = result;
	return CODE_OK;
}

int CrossfireBPManager::commandSetBreakpoints(Value* arguments, IBreakpointTarget** targets, Value** _responseBody, wchar_t** _message) {
	*_responseBody = NULL;

	Value* value_breakpoints = arguments->getObjectValue(KEY_BREAKPOINTS);
	if (!value_breakpoints || value_breakpoints->getType() != TYPE_ARRAY) {
		*_message = _wcsdup(L"'setBreakpoints' command does not have a valid 'breakpoints' value");
		return CODE_INVALID_ARGUMENT;
	}

	std::vector<CrossfireBreakpoint*> bpObjects;

	Value** breakpoints = NULL;
	value_breakpoints->getArrayValues(&breakpoints);
	int index = 0;
	Value* current = breakpoints[index++];
	int code = CODE_OK;
	while (current) {
		CrossfireBreakpoint* breakpoint = NULL;
		code = createBreakpoint(current, &breakpoint, _message);
		if (code != CODE_OK) {
			break;
		}
		bpObjects.push_back(breakpoint);
		current = breakpoints[index++];
	}
	delete[] breakpoints;

	if (code == CODE_OK) {
		Value value_array;
		value_array.setType(TYPE_ARRAY);

		std::vector<CrossfireBreakpoint*>::iterator iterator = bpObjects.begin();
		while (iterator != bpObjects.end()) {
			CrossfireBreakpoint* breakpoint = *iterator;

			/* search registered breakpoints for a duplicate */
			std::map<unsigned int,CrossfireBreakpoint*>::iterator iterator2 = m_breakpoints->begin();
			while (iterator2 != m_breakpoints->end()) {
				CrossfireBreakpoint* current = iterator2->second;
				if (current->matchesLocation(breakpoint)) {
					breakpoint->setHandle(current->getHandle());
					break;
				}
				iterator2++;
			}
			breakpoint->setTarget(this);
			setBreakpoint(breakpoint);
			if (targets) {
				int index = 0;
				IBreakpointTarget* current = targets[index++];
				while (current != NULL) {
					breakpoint->setTarget(current);
					current->setBreakpoint(breakpoint);
					current = targets[index++];
				}
			}

			Value* value_breakpoint = NULL;
			breakpoint->toValueObject(&value_breakpoint);
			value_array.addArrayValue(value_breakpoint);
			delete value_breakpoint;
			delete *iterator;
			iterator++;
		}

		Value* result = new Value();
		result->addObjectValue(KEY_BREAKPOINTS, &value_array);
		*_responseBody = result;
	}

	return code;
}

int CrossfireBPManager::createBreakpoint(Value* arguments, CrossfireBreakpoint** _result, wchar_t** _message) {
	*_result = NULL;

	Value* value_type = arguments->getObjectValue(CrossfireBreakpoint::KEY_TYPE);
	if (!value_type || value_type->getType() != TYPE_STRING) {
		*_message = _wcsdup(L"breakpoint creation arguments do not have a valid 'type' value");
		return CODE_INVALID_ARGUMENT;
	}

	Value* value_attributes = arguments->getObjectValue(CrossfireBreakpoint::KEY_ATTRIBUTES);
	if (value_attributes && value_attributes->getType() != TYPE_OBJECT) {
		*_message = _wcsdup(L"breakpoint creation arguments have an invalid 'attributes' value");
		return CODE_INVALID_ARGUMENT;
	}

	Value* value_location = arguments->getObjectValue(CrossfireBreakpoint::KEY_LOCATION);
	if (!value_location || value_location->getType() != TYPE_OBJECT) {
		*_message = _wcsdup(L"breakpoint creation arguments do not have a valid 'location' value");
		return CODE_INVALID_ARGUMENT;
	}

	CrossfireBreakpoint* breakpoint = NULL;
	wchar_t* type = (wchar_t*)value_type->getStringValue()->c_str();
	if (CrossfireLineBreakpoint::CanHandleBPType(type)) {
		breakpoint = new CrossfireLineBreakpoint();
	} else {
		*_message = _wcsdup(L"breakpoint creation arguments specify an unknown 'type' value");
		return CODE_COMMAND_FAILED;
	}

	if (value_attributes) {
		if (!breakpoint->attributesValueIsValid(value_attributes)) {
			*_message = _wcsdup(L"breakpoint creation arguments specify an invalid attribute name or value");
			delete breakpoint;
			return CODE_COMMAND_FAILED;
		}
		breakpoint->setAttributesFromValue(value_attributes);
	}

	if (!breakpoint->setLocationFromValue(value_location)) {
		*_message = _wcsdup(L"breakpoint creation arguments do not validly specify a location");
		delete breakpoint;
		return CODE_COMMAND_FAILED;
	}

	*_result = breakpoint;
	return CODE_OK;
}

void CrossfireBPManager::setBreakpointsForScript(URL* url, IBreakpointTarget* target) {
	std::map<unsigned int,CrossfireBreakpoint*>::iterator iterator = m_breakpoints->begin();
	while (iterator != m_breakpoints->end()) {
		CrossfireBreakpoint* breakpoint = iterator->second;
		if (breakpoint->appliesToUrl(url)) {
			target->setBreakpoint(breakpoint);
		}
		iterator++;
	}
}
