//
//	SuperAnimCore.js
//
//  Created by Raymond Lu(Raymondlu1105@qq.com)
//  Created by Natural Style Co. Ltd.(window@na-s.jp)
//  
//  All rights reserved.
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//  
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//  
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//
var SuperAnim = SuperAnim = SuperAnim || {};

SuperAnim.SAM_VERSION = 1;
SuperAnim.TWIPS_PER_PIXEL = 20.0;
SuperAnim.LONG_TO_FLOAT = 65536.0;

SuperAnim.FRAMEFLAGS_REMOVES		= 0x01;
SuperAnim.FRAMEFLAGS_ADDS		= 0x02;
SuperAnim.FRAMEFLAGS_MOVES		= 0x04;
SuperAnim.FRAMEFLAGS_FRAME_NAME	= 0x08;

SuperAnim.MOVEFLAGS_ROTATE		= 0x4000;
SuperAnim.MOVEFLAGS_COLOR		= 0x2000;
SuperAnim.MOVEFLAGS_MATRIX		= 0x1000;
SuperAnim.MOVEFLAGS_LONGCOORDS	= 0x0800;



SuperAnim.SuperAnimObject = cc.Class.extend({
	mObjectNum: 0,
	mResNum: 0,
	mTransform: null,
	mColor: null,
	
	ctor: function(){
		this.mTransform = new SuperAnim.SuperAnimTransform();
		this.mColor = new SuperAnim.Color();
	},
});

SuperAnim.SuperAnimImage = cc.Class.extend({
	mSpriteId: null,
	mImageName: '',
	mWidth: 0,
	mHeight: 0,
	mTransform: null,
	
	ctor: function(){
		this.mTransform = new SuperAnim.SuperAnimTransform();
	},
});

SuperAnim.SuperAnimFrame = cc.Class.extend({
	mObjectVector: null,
	
	ctor: function(){
		this.mObjectVector = [];
	},
});

SuperAnim.SuperAnimLabel = cc.Class.extend({
	mLabelName: '',
	mStartFrameNum: 0,
	mEndFrameNum: 0,
	
	ctor: function(){
	},
});

SuperAnim.SuperAnimMainDef = cc.Class.extend({
	mFrames: null,
	mStartFrameNum: 0,
	mEndFrameNum: 0,
	mAnimRate: 0,
	mLabels: null,
	mX: 0,
	mY: 0,
	mWidth: 0,
	mHeight: 0,
	mImageVector: null,
	
	ctor: function(){
		this.mFrames = [];
		this.mLabels = [];
		this.mImageVector = [];
	},
});



SuperAnim.SuperAnimDefMgr = cc.Class.extend({
	mMainDefCache: null,

	ctor: function(){
		this.mMainDefCache = {};
	},
	dtor: function(){
		this.mMainDefCache = {};
	},
	
	// std::string theSuperAnimFile include the absolute path
	LoadSuperAnimMainDef: function(theSuperAnimFile){
		var obj = g_res_sa[theSuperAnimFile];
		
		for(var i=0; i<obj.mImageVector.length; ++i){
			var t = new SuperAnim.SuperAnimTransform();{
				t.mMatrix.m = SuperAnim.cloneObject(obj.mImageVector[i].mTransform.mMatrix.m);
			}
			obj.mImageVector[i].mTransform = t;
			
			obj.mImageVector[i].mSpriteId = SuperAnim.LoadSuperAnimSprite(theSuperAnimFile + obj.mImageVector[i].mImageName);
		}
			
		for(var i=0; i<obj.mFrames.length; ++i)
		{
			for(var j=0; j<obj.mFrames[i].mObjectVector.length; ++j)
			{
				var newT = new SuperAnim.SuperAnimTransform();{
					newT.mMatrix.m = SuperAnim.cloneObject(obj.mFrames[i].mObjectVector[j].mTransform.mMatrix.m);
				}
				obj.mFrames[i].mObjectVector[j].mTransform = newT;
				
				var newC = new SuperAnim.Color(
					obj.mFrames[i].mObjectVector[j].mColor.mRed,
					obj.mFrames[i].mObjectVector[j].mColor.mGreen,
					obj.mFrames[i].mObjectVector[j].mColor.mBlue,
					obj.mFrames[i].mObjectVector[j].mColor.mAlpha);
				obj.mFrames[i].mObjectVector[j].mColor = newC;
			}
		}
		
		
		
		this.mMainDefCache[theSuperAnimFile] = obj;
		
		return true;
	},

	// std::string theSuperAnimFile include the absolute path
	Load_GetSuperAnimMainDef: function(theSuperAnimFile){
		var anItr = this.mMainDefCache[theSuperAnimFile];
		if (anItr)
		{
			return anItr;
		}
		
		if (this.LoadSuperAnimMainDef(theSuperAnimFile) == false)
			return null;
		
		return this.Load_GetSuperAnimMainDef(theSuperAnimFile);
	},
	UnloadSuperAnimMainDef: function(theName){
		var anItr = mMainDefCache[theName];
		if (!anItr)
			return;
		
		// unload the sprites
		for (var i=0; i<anItr.mImageVector.length; ++i)
		{
			var anImage = anItr.mImageVector[i];
			SuperAnim.UnloadSuperSprite(anImage.mSpriteId);
		}
		
		delete mMainDefCache[theName];
	},
});

SuperAnim.SuperAnimDefMgr.sInstance = null;

SuperAnim.SuperAnimDefMgr.GetInstance = function(){
	if (!SuperAnim.SuperAnimDefMgr.sInstance)
	{
		SuperAnim.SuperAnimDefMgr.sInstance = new SuperAnim.SuperAnimDefMgr();
	}
	
	return SuperAnim.SuperAnimDefMgr.sInstance;
};

SuperAnim.SuperAnimDefMgr.DestroyInstance = function(){
	if (SuperAnim.SuperAnimDefMgr.sInstance)
	{
		SuperAnim.SuperAnimDefMgr.sInstance = null;
	}
};



SuperAnim.GetSuperAnimHandler = function(theAbsAnimFile){
	var aSuperAnimHander = new SuperAnim.SuperAnimHandler();
	
	var aMainDef = SuperAnim.SuperAnimDefMgr.GetInstance().Load_GetSuperAnimMainDef(theAbsAnimFile);
	if (aMainDef) {
		aSuperAnimHander.mMainDefKey = theAbsAnimFile; // right now just use the animation file name as the key
		aSuperAnimHander.mAnimRate = aMainDef.mAnimRate;
		aSuperAnimHander.mWidth = aMainDef.mWidth;
		aSuperAnimHander.mHeight = aMainDef.mHeight;
		aSuperAnimHander.mCurFrameNum = aMainDef.mStartFrameNum;
		aSuperAnimHander.mIsHandlerValid = true;
	} else {
		aSuperAnimHander.mIsHandlerValid = false;
	}
	
	return aSuperAnimHander;
};

SuperAnim.sAnimObjIndex = 0;
SuperAnim.sShouldStartAnimObjDrawItr = false;
SuperAnim.BeginIterateAnimObjDrawInfo = function(){
	SuperAnim.sAnimObjIndex = 0;
	SuperAnim.sShouldStartAnimObjDrawItr = true;
};

SuperAnim.IterateAnimObjDrawInfo = function(theHandler, theOutputObjDrawInfo){
	if (!SuperAnim.sShouldStartAnimObjDrawItr) {
		//assert(false && "Forgot to call SuperAnim.BeginIterateAnimObjDrawInfo?");
		return false;
	}
	
	if (!theHandler.IsValid()) {
		//assert(false && "The Animation handler is not valid.");
		return false;
	}
	
	var aMainDef = SuperAnim.SuperAnimDefMgr.GetInstance().Load_GetSuperAnimMainDef(theHandler.mMainDefKey);
	if (!aMainDef) {
		//assert(false && "I can't find the Animation definition.");
		return false;
	}
	
	var aCurFrameNum = Math.floor(theHandler.mCurFrameNum);
	var aCurFrame = aMainDef.mFrames[aCurFrameNum];
	if (SuperAnim.sAnimObjIndex >= aCurFrame.mObjectVector.length) {
		// we have iterated all objects in this frame
		SuperAnim.sShouldStartAnimObjDrawItr = false;
		return false;
	}
	
	var aCurObject = aCurFrame.mObjectVector[SuperAnim.sAnimObjIndex];
	
	// find the image, fill the sprite id
	var aSuperAnimImage = aMainDef.mImageVector[aCurObject.mResNum];
	theOutputObjDrawInfo.mSpriteId = aSuperAnimImage.mSpriteId;
	
	// do the interpolateion to next frame for transform & color
	if (aCurFrameNum == aMainDef.mEndFrameNum) {
		// reach the end frame, don't need to do any interpolation
		theOutputObjDrawInfo.mTransform = aCurObject.mTransform;
		theOutputObjDrawInfo.mColor = aCurObject.mColor;
	} else {
		var aNextFrameNum = aCurFrameNum + 1;
		var finishedInterp = false;
		var aNextFrame = aMainDef.mFrames[aNextFrameNum];
		for (var i = 0; i < aNextFrame.mObjectVector.length; ++i) {
			var anObj = aNextFrame.mObjectVector[i];
			if (anObj.mObjectNum == aCurObject.mObjectNum && anObj.mResNum == aCurObject.mResNum) {
				var anInterp = theHandler.mCurFrameNum - aCurFrameNum;
				theOutputObjDrawInfo.mTransform = aCurObject.mTransform.InterpolateTo(anObj.mTransform, anInterp);
				theOutputObjDrawInfo.mColor = aCurObject.mColor.InterpolateTo(anObj.mColor, anInterp);
				finishedInterp = true;
				break;
			}
		}
		if (!finishedInterp) {
			// we miss the object in next frame?
			// never mind
			theOutputObjDrawInfo.mTransform = SuperAnim.cloneObject(aCurObject.mTransform);
			theOutputObjDrawInfo.mColor = SuperAnim.cloneObject(aCurObject.mColor);
		}
	}
	
	theOutputObjDrawInfo.mTransform = theOutputObjDrawInfo.mTransform.TransformSrc(aSuperAnimImage.mTransform);
	var aMatrix = new SuperAnim.SuperAnimMatrix3();
	aMatrix.LoadIdentity();
	aMatrix.m[0][2] = aSuperAnimImage.mWidth * 0.5;
	aMatrix.m[1][2] = aSuperAnimImage.mHeight * 0.5;
	theOutputObjDrawInfo.mTransform.mMatrix = theOutputObjDrawInfo.mTransform.mMatrix.op_ast(aMatrix);
	
	SuperAnim.sAnimObjIndex++;
	return true;
};

SuperAnim.IncAnimFrameNum = function(theMainDefHandler, theDeltaTime, hitNewLabel){
	
	if (!theMainDefHandler.IsValid()) {
		return;
	}
	
	var aLastFrameNum = Math.floor(theMainDefHandler.mCurFrameNum);
	theMainDefHandler.mCurFrameNum += theDeltaTime * theMainDefHandler.mAnimRate;
	var aCurFrame = Math.floor(theMainDefHandler.mCurFrameNum);
	
	if (aCurFrame != aLastFrameNum) // Reach new frame
	{
		// Check whether reach a new label frame
		var aIsNewLabel = false;
		if (aCurFrame >= theMainDefHandler.mLastFrameNumOfCurLabel) {
			theMainDefHandler.mCurFrameNum = theMainDefHandler.mLastFrameNumOfCurLabel;
			aIsNewLabel = true;
		}
		
		hitNewLabel[0] = aIsNewLabel;
	}
};

SuperAnim.HasSection = function(theHandler, theLabelName){
	var aMainDef = SuperAnim.SuperAnimDefMgr.GetInstance().Load_GetSuperAnimMainDef(theHandler.mMainDefKey);
	if (!aMainDef) {
		return false;
	}
	for (var i=0; i<aMainDef.mLabels.length; ++i)
	{
		if (aMainDef.mLabels[i].mLabelName == theLabelName)
			return true;
	}
	
	return false;
};

SuperAnim.PlayBySection = function(theHandler, theLabelName){	
	var aMainDef = SuperAnim.SuperAnimDefMgr.GetInstance().Load_GetSuperAnimMainDef(theHandler.mMainDefKey);
	if (!aMainDef) {
		theHandler.mIsHandlerValid = false;
		return false;
	}
	for (var i=0; i<aMainDef.mLabels.length; ++i)
	{
		if (aMainDef.mLabels[i].mLabelName == theLabelName)
		{
			theHandler.mCurFrameNum = aMainDef.mLabels[i].mStartFrameNum;
			theHandler.mCurLabel = theLabelName;
			theHandler.mFirstFrameNumOfCurLabel = aMainDef.mLabels[i].mStartFrameNum;
			theHandler.mLastFrameNumOfCurLabel = aMainDef.mLabels[i].mEndFrameNum;
			theHandler.mIsHandlerValid = true;
			return true;
		}
	}
	
	theHandler.mIsHandlerValid = false;
	return false;
};

SuperAnim.LoadAnimFile = function(theAbsAnimFile){
	return SuperAnim.SuperAnimDefMgr.GetInstance().Load_GetSuperAnimMainDef(theAbsAnimFile) != null;
};

SuperAnim.UnloadAnimFile = function(theAbsAnimFile){
	SuperAnim.SuperAnimDefMgr.GetInstance().UnloadSuperAnimMainDef(theAbsAnimFile);
};

SuperAnim.cloneObject = function(obj) {
        var clone = {};
        for(var i in obj) {
            if(typeof(obj[i])=="object")
                clone[i] = SuperAnim.cloneObject(obj[i]);
            else
                clone[i] = obj[i];
        }
        return clone;
}








