/*
* Copyright 2006 Sony Computer Entertainment Inc.
*
* Licensed under the MIT Open Source License, for details please see license.txt or the website
* http://www.opensource.org/licenses/mit-license.php
*
*/ 

#include <list>
#include <vector>
#include <sstream>
#include <algorithm>
#include <dae/daeSIDResolver.h>
#include <dae/daeIDRef.h>
#include <dae/daeAtomicType.h>
#include <dae/daeMetaAttribute.h>
#include <dae/daeMetaElement.h>
#include <dae/daeURI.h>
#include <dom/domTypes.h>
#include <dom/domConstants.h>
#include <dae/daeDocument.h>
#include <dae/daeDatabase.h>
#include <dae/daeUtils.h>
#include <dom/domSource.h>

using namespace std;


namespace {
	template<typename T>
	T nextIter(const T& iter) {
		T next = iter;
		return ++next;
	}

	template<typename T>
	T moveIter(const T& iter, int n) {
		T result = iter;
		advance(result, n);
		return result;
	}
	
	// Implements a breadth-first sid search by starting at the container element and
	// traversing downward through the element tree.
	daeElement* findSidTopDown(daeElement* container, const string& sid, const string& profile) {
		if (!container)
			return NULL;

		vector<daeElement*> elts, matchingElts;
		elts.push_back(container);

		for (size_t i = 0; i < elts.size(); i++) {
			daeElement* elt = elts[i];
			
			// Bail if we're looking for an element in a different profile
			if (!profile.empty()) {
				if (strcmp(elt->getElementName(), COLLADA_ELEMENT_TECHNIQUE_COMMON) == 0)
					continue;
				if (strcmp(elt->getElementName(), COLLADA_ELEMENT_TECHNIQUE) == 0  &&
				    profile != elt->getAttribute("profile"))
					continue;
			}
		
			// See if this is a matching element
			if (elt->getAttribute("sid") == sid)
				return elt;
			else {
				// Add the children to the list of elements to check
				daeElementRefArray children;
				elt->getChildren(children);
				for (size_t j = 0; j < children.getCount(); j++)
					elts.push_back(children[j]);
			}
		}

		return NULL;
	}

	// Returns the distance between an element and an ancestor of the element. If 'container
	// isn't an ancestor of 'elt', or if 'elt' is in a profile that doesn't match 'profile'
	// UINT_MAX is returned.
	unsigned int computeDistance(daeElement* container, daeElement* elt, const string& profile) {
		if (!container || !elt)
			return UINT_MAX;

		unsigned int distance = 0;
		do {
			// Bail if we're looking for an element in a different profile
			if (!profile.empty()) {
				if (strcmp(elt->getElementName(), COLLADA_ELEMENT_TECHNIQUE_COMMON) == 0)
					return UINT_MAX;
				if (strcmp(elt->getElementName(), COLLADA_ELEMENT_TECHNIQUE) == 0  &&
				    profile != elt->getAttribute("profile"))
					return UINT_MAX;
			}

			if (elt == container)
				return distance;
			distance++;
		} while ((elt = elt->getParentElement()) != NULL);

		return UINT_MAX;
	}

	// Implements a breadth-first sid search by using the database to find all elements
	// matching 'sid', then finding the element closest to 'container'.
	daeElement* findSidBottomUp(daeElement* container, const string& sid, const string& profile) {
		if (!container || !container->getDocument())
			return NULL;

		// Get the elements with a matching sid
		vector<daeElement*> elts;
		container->getDocument()->getDAE()->getDatabase()->sidLookup(sid, elts, container->getDocument());

		// Compute the distance from each matching element to the container element
		unsigned int minDistance = UINT_MAX;
		daeElement* closestElt = NULL;
		for (size_t i = 0; i < elts.size(); i++) {
			unsigned int distance = computeDistance(container, elts[i], profile);
			if (distance < minDistance) {
				minDistance = distance;
				closestElt = elts[i];
			}
		}

		return closestElt;
	}

	daeElement* findID(daeElement* elt, const string& id, const string& profile) {
		return elt ? elt->getDAE()->getDatabase()->idLookup(id, elt->getDocument()) : NULL;
	}
	
	void buildString(const list<string>::iterator& begin,
	                 const list<string>::iterator& end,
	                 string& result) {
		ostringstream stream;
		for (list<string>::iterator iter = begin; iter != end; iter++)
			stream << *iter;
		result = stream.str();
	}

	// Finds an element with a matching ID or sid (depending on the 'finder' function)
	// passed in. First it tries to resolve the whole ID/sid, then it tries to resolve
	// successively smaller parts. For example, consider this sid ref: "my.sid.ref".
	// First this function will try to resolve "my.sid.ref" entirely, then if that
	// fails it'll try to resolve "my.sid.", "my.sid", "my.", and "my", in that order.
	// The part that wasn't matched is returned in the 'remainingPart' parameter.
	daeElement* findWithDots(daeElement* container,
	                         const string& s,
	                         const string& profile,
	                         daeElement* (*finder)(daeElement*, const string&, const string&),
	                         list<string>& remainingPart) {
		remainingPart.clear();

		// First see if the whole thing resolves correctly
		if (daeElement* result = finder(container, s, profile))
			return result;

		// It didn't resolve. Let's tokenize it by '.'s and see if we can resolve a
		// portion of it.
		cdom::tokenize(s, ".", remainingPart, true);
		if (remainingPart.size() == 1)
			return NULL; // There were no '.'s, so the result won't be any different

		list<string>::iterator iter = moveIter(remainingPart.end(), -1);
		for (int i = int(remainingPart.size())-1; i >= 1; i--, iter--) {
			string substr;
			buildString(remainingPart.begin(), iter, substr);
			if (daeElement* result = finder(container, substr, profile)) {
				// Remove the part we matched against from the list
				remainingPart.erase(remainingPart.begin(), iter);
				return result;
			}
		}

		remainingPart.clear();
		return NULL;
	}

	daeSidRef::resolveData resolveImpl(const daeSidRef& sidRef) {
		if (sidRef.sidRef.empty() || !sidRef.refElt)
			return daeSidRef::resolveData();

		daeSidRef::resolveData result;
		string separators = "/()";
		list<string> tokens;
		cdom::tokenize(sidRef.sidRef, separators, /* out */ tokens, true);

		list<string>::iterator tok = tokens.begin();

		// The first token should be either an ID or a '.' to indicate
		// that we should start the search from the container element.
		if (tok == tokens.end())
			return daeSidRef::resolveData();

		list<string> remainingPart;
		if (*tok == ".") {
			result.elt = sidRef.refElt;
			tok++;
		}	else {
			// Try to resolve it as an ID
			result.elt = findWithDots(sidRef.refElt, *tok, sidRef.profile, findID, remainingPart);
			if (result.elt) {
				if (!remainingPart.empty()) {
					// Insert the "remaining part" from the ID resolve into our list of tokens
					tokens.erase(tokens.begin());
					tokens.splice(tokens.begin(), remainingPart);
					tok = tokens.begin();
				} else
					tok++;
			}
		}

		if (!result.elt)
			return daeSidRef::resolveData();

		// Next we have an optional list of SIDs, each one separated by "/". Once we hit one of "()",
		// we know we're done with the SID section.
		for (; tok != tokens.end() && *tok == "/"; tok++) {
			tok++; // Read the '/'
			if (tok == tokens.end())
				return daeSidRef::resolveData();

			// Find the element matching the SID
			result.elt = findWithDots(result.elt, *tok, sidRef.profile, findSidTopDown, remainingPart);
			if (!result.elt)
				return daeSidRef::resolveData();

			if (!remainingPart.empty()) {
				list<string>::iterator tmp = tok;
				tok--;
				tokens.splice(tmp, remainingPart);
				tokens.erase(tmp);
			}
		}

		// Now we want to parse the member selection tokens. It can either be
		//   (a) '.' followed by a string representing the member to access
		//   (b) '(x)' where x is a number, optionally followed by another '(x)'
		// Anything else is an error.
		string member;
		bool haveArrayIndex1 = false, haveArrayIndex2 = false;
		int arrayIndex1 = -1, arrayIndex2 = -1;
		if (tok != tokens.end()) {
			if (*tok == ".") {
				tok++;
				if (tok == tokens.end())
					return daeSidRef::resolveData();
				member = *tok;
				tok++;
			}
			else if (*tok == "(") {
				tok++;
				if (tok == tokens.end())
					return daeSidRef::resolveData();

				istringstream stream(*tok);
				stream >> arrayIndex1;
				haveArrayIndex1 = true;
				if (!stream.good() && !stream.eof())
					return daeSidRef::resolveData();
				tok++;
				if (tok == tokens.end()  ||  *tok != ")")
					return daeSidRef::resolveData();
				tok++;
			
				if (tok != tokens.end()  &&  *tok == "(") {
					tok++;
					if (tok == tokens.end())
						return daeSidRef::resolveData();

					stream.clear();
					stream.str(*tok);
					stream >> arrayIndex2;
					haveArrayIndex2 = true;
					if (!stream.good() && !stream.eof())
						return daeSidRef::resolveData();
					tok++;
					if (tok == tokens.end()  ||  *tok != ")")
						return daeSidRef::resolveData();
					tok++;
				}
			}
		}

		// We shouldn't have any tokens left. If we do it's an error.
		if (tok != tokens.end())
			return daeSidRef::resolveData();

		// At this point we've parsed a correctly formatted SID reference. The only thing left is to resolve
		// the member selection portion of the SID ref. First, see if the resolved element has a float array we
		// can use.
		if (result.elt->typeID() == domSource::ID()) {
			if (domFloat_array* floatArray = ((domSource*)result.elt)->getFloat_array())
				result.array = (daeDoubleArray*)floatArray->getCharDataObject()->get(floatArray);
		}
		else 
		{
			daeMetaAttribute *ma = result.elt->getCharDataObject();
			if ( ma != NULL ) {
				if ( ma->isArrayAttribute() && ma->getType()->getTypeEnum() == daeAtomicType::DoubleType ) {
					result.array = (daeDoubleArray*)ma->get( result.elt );
				}
			}
		}

		if( result.array ) {
			// We have an array to use for indexing. Let's see if the SID ref uses member selection.
			if (!member.empty()) {
				// Do member lookup based on the constants defined in the COMMON profile
				if (member == "ANGLE") {
					result.scalar = &(result.array->get(3));
				}	else if (member.length() == 1) {
					switch(member[0]) {
					case 'X':
					case 'R':
					case 'U':
					case 'S':
						result.scalar = &(result.array->get(0));
						break;
					case 'Y':
					case 'G':
					case 'V':
					case 'T':
						result.scalar = &(result.array->get(1));
						break;
					case 'Z':
					case 'B':
					case 'P':
						result.scalar = &(result.array->get(2));
						break;
					case 'W':
					case 'A':
					case 'Q':
						result.scalar = &(result.array->get(3));
						break;
					};
				}
			} else if (haveArrayIndex1) {
				// Use the indices to lookup a value in the array
				if (haveArrayIndex2  &&  result.array->getCount() == 16) {
					// We're doing a matrix lookup. Make sure the index is valid.
					int i = arrayIndex1*4 + arrayIndex2;
					if (i >= 0  &&  i < int(result.array->getCount()))
						result.scalar = &(result.array->get(i));
				} else {
					// Vector lookup. Make sure the index is valid.
					if (arrayIndex1 >= 0  &&  arrayIndex1 < int(result.array->getCount()))
						result.scalar = &(result.array->get(arrayIndex1));
				}
			}
		}

		// If we tried to do member selection but we couldn't resolve it to a doublePtr, fail.
		if ((!member.empty() || haveArrayIndex1)  &&  result.scalar == NULL)
			return daeSidRef::resolveData();

		// SID resolution was successful.
		return result;
	}
} // namespace {


daeSidRef::resolveData::resolveData() : elt(NULL), array(NULL), scalar(NULL) { }

daeSidRef::resolveData::resolveData(daeElement* elt, daeDoubleArray* array, daeDouble* scalar)
  : elt(elt),
    array(array),
    scalar(scalar) { }


daeSidRef::daeSidRef() : refElt(NULL) { }

daeSidRef::daeSidRef(const string& sidRef, daeElement* referenceElt, const string& profile)
  : sidRef(sidRef),
    refElt(referenceElt),
    profile(profile) { }

bool daeSidRef::operator<(const daeSidRef& other) const {
	if (refElt != other.refElt)
		return refElt < other.refElt;
	if (sidRef != other.sidRef)
		return sidRef < other.sidRef;
	return profile < other.profile;
}

daeSidRef::resolveData daeSidRef::resolve() {
	if (!refElt)
		return daeSidRef::resolveData();
	
	// First check the cache
	daeSidRef::resolveData result = refElt->getDAE()->getSidRefCache().lookup(*this);
	if (result.elt)
		return result;

	// Try to resolve as an effect-style sid ref by prepending "./" to the sid ref.
	// If that fails, try resolving as an animation-style sid ref, where the first part is an ID.
	result = resolveImpl(daeSidRef(string("./") + sidRef, refElt, profile));
	if (!result.elt)
		result = resolveImpl(*this);

	if (result.elt) // Add the result to the cache
		refElt->getDAE()->getSidRefCache().add(*this, result);

	return result;
}


daeSIDResolver::daeSIDResolver( daeElement *container, daeString target, daeString profile )
	: container(NULL)
{
	setContainer(container);
	setTarget(target);
	setProfile(profile);
}

daeString daeSIDResolver::getTarget() const {
	return target.empty() ? NULL : target.c_str();
}

void daeSIDResolver::setTarget( daeString t )
{
	target = t ? t : "";
}

daeString daeSIDResolver::getProfile() const {
	return profile.empty() ? NULL : profile.c_str();
}

void daeSIDResolver::setProfile( daeString p )
{
	profile = p ? p : "";
}

daeElement* daeSIDResolver::getContainer() const {
	return container;
}

void daeSIDResolver::setContainer(daeElement* element)
{
	container = element;
}

daeSIDResolver::ResolveState daeSIDResolver::getState() const {
	if (target.empty())
		return target_empty;

	daeSidRef::resolveData result = daeSidRef(target, container, profile).resolve();
	if (!result.elt)
		return sid_failed_not_found;
	if (result.scalar)
		return sid_success_double;
	if (result.array)
		return sid_success_array;

	return sid_success_element;
}

daeElement* daeSIDResolver::getElement()
{
	return daeSidRef(target, container, profile).resolve().elt;
}

daeDoubleArray *daeSIDResolver::getDoubleArray()
{
	return daeSidRef(target, container, profile).resolve().array;
}

daeDouble *daeSIDResolver::getDouble()
{
	return daeSidRef(target, container, profile).resolve().scalar;
}


daeSidRefCache::daeSidRefCache() : hitCount(0), missCount(0) { }

daeSidRef::resolveData daeSidRefCache::lookup(const daeSidRef& sidRef) {
	map<daeSidRef, daeSidRef::resolveData>::iterator iter = lookupTable.find(sidRef);
	if (iter != lookupTable.end()) {
		hitCount++;
		return iter->second;
	}
	missCount++;
	return daeSidRef::resolveData();
}

void daeSidRefCache::add(const daeSidRef& sidRef, const daeSidRef::resolveData& result) {
	lookupTable[sidRef] = result;
}

void daeSidRefCache::clear() {
	lookupTable.clear();
	hitCount = missCount = 0;
}

bool daeSidRefCache::empty() {
	return lookupTable.empty();
}

int daeSidRefCache::misses() {
	return missCount;
}

int daeSidRefCache::hits() {
	return hitCount;
}
