/*==LICENSE==*

CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011  Cyan Worlds, Inc.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

You can contact Cyan Worlds, Inc. by email legal@cyan.com
 or by snail mail at:
      Cyan Worlds, Inc.
      14617 N Newport Hwy
      Mead, WA   99021

*==LICENSE==*/

#include "hsTypes.h"
#include "hsTimer.h"
#include "plLayerAnimation.h"
#include "pnKeyedObject/plKey.h"

#include "plInterp/plController.h"
#include "plMessage/plAnimCmdMsg.h"
#include "plMessage/plLinkToAgeMsg.h"
#include "pnMessage/plSDLModifierMsg.h"
#include "plModifier/plLayerSDLModifier.h"
#include "pnMessage/plCameraMsg.h"
#include "plNetClient/plLinkEffectsMgr.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
#include "plModifier/plSDLModifier.h"
#include "plSDL/plSDL.h"
#include "pnMessage/plSDLNotificationMsg.h"
#include "plMessage/plAvatarMsg.h"

plLayerAnimationBase::plLayerAnimationBase()
: 
	fPreshadeColorCtl(nil), 
	fRuntimeColorCtl(nil),
	fAmbientColorCtl(nil), 
	fSpecularColorCtl(nil),
	fOpacityCtl(nil), 
	fTransformCtl(nil),
	fEvalTime(-1.0),
	fCurrentTime(-1.f),
	fSegmentID(nil)
{
}

plLayerAnimationBase::~plLayerAnimationBase()
{
	delete fPreshadeColorCtl;
	delete fRuntimeColorCtl;
	delete fAmbientColorCtl;
	delete fSpecularColorCtl;
	delete fOpacityCtl;
	delete fTransformCtl;
	delete [] fSegmentID;
}

void plLayerAnimationBase::Read(hsStream* s, hsResMgr* mgr)
{
	plLayerInterface::Read(s, mgr);

	fPreshadeColorCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
	fRuntimeColorCtl = plController::ConvertNoRef( mgr->ReadCreatable( s ) );
	fAmbientColorCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
	fSpecularColorCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
	fOpacityCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
	fTransformCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));

	if( fOpacityCtl )
	{
		fOwnedChannels |= kOpacity;
		fOpacity = TRACKED_NEW hsScalar;
	}
	if( fPreshadeColorCtl )
	{
		fOwnedChannels |= kPreshadeColor;
		fPreshadeColor = TRACKED_NEW hsColorRGBA;
	}
	if( fRuntimeColorCtl )
	{
		fOwnedChannels |= kRuntimeColor;
		fRuntimeColor = TRACKED_NEW hsColorRGBA;
	}
	if( fAmbientColorCtl )
	{
		fOwnedChannels |= kAmbientColor;
		fAmbientColor = TRACKED_NEW hsColorRGBA;
	}
	if( fSpecularColorCtl )
	{
		fOwnedChannels |= kSpecularColor;
		fSpecularColor = TRACKED_NEW hsColorRGBA;
	}
	if( fTransformCtl )
	{
		fOwnedChannels |= kTransform;
		fTransform = TRACKED_NEW hsMatrix44;
	}
	fLength = IMakeUniformLength();
}

void plLayerAnimationBase::Write(hsStream* s, hsResMgr* mgr)
{
	plLayerInterface::Write(s, mgr);

	mgr->WriteCreatable(s, fPreshadeColorCtl);
	mgr->WriteCreatable(s, fRuntimeColorCtl);
	mgr->WriteCreatable(s, fAmbientColorCtl);
	mgr->WriteCreatable(s, fSpecularColorCtl);
	mgr->WriteCreatable(s, fOpacityCtl);
	mgr->WriteCreatable(s, fTransformCtl);
}

plLayerInterface* plLayerAnimationBase::Attach(plLayerInterface* prev)
{
	return plLayerInterface::Attach(prev);
}

void plLayerAnimationBase::IEvalConvertedTime(hsScalar secs, UInt32 passChans, UInt32 evalChans, UInt32 &dirty)
{
	if( evalChans & kPreshadeColor )
	{
		fPreshadeColorCtl->Interp(fCurrentTime, fPreshadeColor);
		dirty |= kPreshadeColor;
	}
	else if( passChans & kPreshadeColor )
	{
		*fPreshadeColor = fUnderLay->GetPreshadeColor();
	}

	if( evalChans & kRuntimeColor )
	{
		fRuntimeColorCtl->Interp( fCurrentTime, fRuntimeColor );
		dirty |= kRuntimeColor;
	}
	else if( passChans & kRuntimeColor )
	{
		*fRuntimeColor = fUnderLay->GetRuntimeColor();
	}

	if( evalChans & kAmbientColor )
	{
		fAmbientColorCtl->Interp(fCurrentTime, fAmbientColor);
		dirty |= kAmbientColor;
	}
	else if( passChans & kAmbientColor )
	{
		*fAmbientColor = fUnderLay->GetAmbientColor();
	}

	if( evalChans & kSpecularColor )
	{
		fSpecularColorCtl->Interp( fCurrentTime, fSpecularColor );
		dirty |= kSpecularColor;
	}
	else if( passChans & kSpecularColor )
	{
		*fSpecularColor = fUnderLay->GetSpecularColor();
	}

	if( evalChans & kOpacity )
	{
		fOpacityCtl->Interp(fCurrentTime, fOpacity);
		*fOpacity *= 1.e-2f;
		dirty |= kOpacity;
	}
	else if( passChans & kOpacity )
	{
		*fOpacity = fUnderLay->GetOpacity();
	}

	if( evalChans & kTransform )
	{
		fTransformCtl->Interp(fCurrentTime, fTransform);
		dirty |= kTransform;
	}
	else if( passChans & kTransform )
	{
		*fTransform = fUnderLay->GetTransform();
	}
	fPassThruChannels = 0; // already handled, don't need to keep passing them through.
}

hsBool plLayerAnimationBase::MsgReceive(plMessage* msg)
{
	return plLayerInterface::MsgReceive(msg);
}

void plLayerAnimationBase::SetPreshadeColorCtl(plController* colCtl)
{
	if( fPreshadeColorCtl )
		delete fPreshadeColorCtl;
	else
		fPreshadeColor = TRACKED_NEW hsColorRGBA;

	fOwnedChannels |= kPreshadeColor;
	fPreshadeColorCtl = colCtl;
}

void plLayerAnimationBase::SetRuntimeColorCtl(plController* colCtl)
{
	if( fRuntimeColorCtl )
		delete fRuntimeColorCtl;
	else
		fRuntimeColor = TRACKED_NEW hsColorRGBA;

	fOwnedChannels |= kRuntimeColor;
	fRuntimeColorCtl = colCtl;
}

void plLayerAnimationBase::SetAmbientColorCtl(plController* ambCtl)
{
	if( fAmbientColorCtl )
		delete fAmbientColorCtl;
	else
		fAmbientColor = TRACKED_NEW hsColorRGBA;

	fOwnedChannels |= kAmbientColor;
	fAmbientColorCtl = ambCtl;
}

void plLayerAnimationBase::SetSpecularColorCtl(plController* ambCtl)
{
	if( fSpecularColorCtl )
		delete fSpecularColorCtl;
	else
		fSpecularColor = TRACKED_NEW hsColorRGBA;

	fOwnedChannels |= kSpecularColor;
	fSpecularColorCtl = ambCtl;
}

void plLayerAnimationBase::SetOpacityCtl(plController* opaCtl)
{
	if( fOpacityCtl )
		delete fOpacityCtl;
	else
		fOpacity = TRACKED_NEW hsScalar;

	fOwnedChannels |= kOpacity;
	fOpacityCtl = opaCtl;
}

void plLayerAnimationBase::SetTransformCtl(plController* xfmCtl)
{
	if( fTransformCtl )
		delete fTransformCtl;
	else
		fTransform = TRACKED_NEW hsMatrix44;

	fOwnedChannels |= kTransform;
	fTransformCtl = xfmCtl;
}

hsScalar plLayerAnimationBase::IMakeUniformLength()
{
	fLength = 0;
	if( fPreshadeColorCtl && (fPreshadeColorCtl->GetLength() > fLength) )
		fLength = fPreshadeColorCtl->GetLength();
	if( fRuntimeColorCtl && (fRuntimeColorCtl->GetLength() > fLength) )
		fLength = fRuntimeColorCtl->GetLength();
	if( fAmbientColorCtl && (fAmbientColorCtl->GetLength() > fLength) )
		fLength = fAmbientColorCtl->GetLength();
	if( fSpecularColorCtl && (fSpecularColorCtl->GetLength() > fLength) )
		fLength = fSpecularColorCtl->GetLength();
	if( fOpacityCtl && (fOpacityCtl->GetLength() > fLength) )
		fLength = fOpacityCtl->GetLength();
	if( fTransformCtl && (fTransformCtl->GetLength() > fLength) )
		fLength = fTransformCtl->GetLength();

	return fLength;
}

/////////////////////////////////////////////////////////////////////////////////

plLayerAnimation::plLayerAnimation()
:
	plLayerAnimationBase(),
	fLayerSDLMod(nil)
{
	fTimeConvert.SetOwner(this);
}

plLayerAnimation::~plLayerAnimation()
{
	delete fLayerSDLMod;
}

void plLayerAnimation::Read(hsStream* s, hsResMgr* mgr)
{
	plLayerAnimationBase::Read(s, mgr);

	fTimeConvert.Read(s, mgr);	
	if (!(fTimeConvert.IsStopped()))
	{	
		plSynchEnabler ps(true);	// enable dirty tracking so that we send state about
									// the anim resetting to start now.
		fTimeConvert.SetCurrentAnimTime(0, true);
	}
	Eval(hsTimer::GetSysSeconds(),0,0);

	// add sdl modifier
	delete fLayerSDLMod;
	fLayerSDLMod = TRACKED_NEW plLayerSDLModifier;
	fLayerSDLMod->SetLayerAnimation(this);
}


void plLayerAnimation::Write(hsStream* s, hsResMgr* mgr)
{
	plLayerAnimationBase::Write(s, mgr);

	fTimeConvert.Write(s, mgr);
}

plLayerInterface* plLayerAnimation::Attach(plLayerInterface* prev)
{
	fCurrentTime = fTimeConvert.CurrentAnimTime()-1.f;

	return plLayerAnimationBase::Attach(prev);
}

UInt32 plLayerAnimation::Eval(double wSecs, UInt32 frame, UInt32 ignore)
{
	UInt32 dirty = plLayerInterface::Eval(wSecs, frame, ignore);
	if( wSecs != fEvalTime )
	{
		UInt32 evalChans = 0;
		UInt32 passChans = dirty | fPassThruChannels;
		hsScalar secs = fTimeConvert.WorldToAnimTime(wSecs);
		if( secs != fCurrentTime )
		{
			evalChans = fOwnedChannels & ~ignore & ~fPassThruChannels;
			fCurrentTime = secs;
		}

		IEvalConvertedTime(secs, passChans, evalChans, dirty);
	}
	fEvalTime = wSecs;
	return dirty;
}

hsBool plLayerAnimation::MsgReceive(plMessage* msg)
{
	// pass sdl msg to sdlMod
	plSDLModifierMsg* sdlMsg = plSDLModifierMsg::ConvertNoRef(msg);
	if (sdlMsg && fLayerSDLMod)
	{
		if (fLayerSDLMod->MsgReceive(sdlMsg))
			return true;	// msg handled
	}

	hsBool retVal = false;
	plAnimCmdMsg* cmdMsg = plAnimCmdMsg::ConvertNoRef(msg);
	if( cmdMsg )
	{
		// Evaluate first, so we'll be transitioning from our
		// real current state, whether we've been evaluated (in view)
		// lately or not.
		TopOfStack()->Eval(hsTimer::GetSysSeconds(), 0, 0);
		retVal = fTimeConvert.HandleCmd(cmdMsg);
		DirtySynchState(kSDLLayer, 0);
	}

	if( retVal )
	{
		if( !fTimeConvert.IsStopped() || fTimeConvert.GetFlag(plAnimTimeConvert::kForcedMove) )
		{
			ClaimChannels(fOwnedChannels);
			fCurrentTime = -1.f; // force an eval
		}
	}
	else
	{
		retVal = plLayerAnimationBase::MsgReceive(msg);
	}
	
	return retVal;
}

void plLayerAnimation::DefaultAnimation()
{
	IMakeUniformLength();
	fTimeConvert.SetBegin(0);
	fTimeConvert.SetEnd(fLength);
	fTimeConvert.SetLoopPoints(0,fLength);
	fTimeConvert.Loop();
	fTimeConvert.Start();
}

///////////////////////////////////////////////////////////////////////////////////////

plLayerLinkAnimation::plLayerLinkAnimation() : 
	fLinkKey(nil), 
	fLeavingAge(true),
	fEnabled(true), 
	fFadeFlags(0), 
	fLastFadeFlag(0),
	fFadeFlagsDirty(false) 
{ 
	fIFaceCallback = TRACKED_NEW plEventCallbackMsg();
	fIFaceCallback->fEvent = kTime;
	fIFaceCallback->fRepeats = 0;			
}

plLayerLinkAnimation::~plLayerLinkAnimation() 
{ 
	hsRefCnt_SafeUnRef(fIFaceCallback);
}


void plLayerLinkAnimation::Read(hsStream* s, hsResMgr* mgr)
{
	plLayerAnimation::Read(s, mgr);
	
	fLinkKey = mgr->ReadKey(s);
	fLeavingAge = s->ReadBool();
	plgDispatch::Dispatch()->RegisterForExactType(plLinkEffectBCMsg::Index(), GetKey());
	plgDispatch::Dispatch()->RegisterForExactType(plLinkEffectPrepBCMsg::Index(), GetKey());
	plgDispatch::Dispatch()->RegisterForExactType(plCameraTargetFadeMsg::Index(), GetKey());
	plgDispatch::Dispatch()->RegisterForExactType(plAvatarStealthModeMsg::Index(), GetKey());
	plgDispatch::Dispatch()->RegisterForExactType(plIfaceFadeAvatarMsg::Index(), GetKey());
	plgDispatch::Dispatch()->RegisterForExactType(plPseudoLinkAnimTriggerMsg::Index(), GetKey());
	
	fIFaceCallback->AddReceiver(GetKey());	
}


void plLayerLinkAnimation::Write(hsStream* s, hsResMgr* mgr)
{
	plLayerAnimation::Write(s, mgr);
	
	mgr->WriteKey(s, fLinkKey);
	s->WriteBool(fLeavingAge);
}

UInt32 plLayerLinkAnimation::Eval(double wSecs, UInt32 frame, UInt32 ignore)
{
	UInt32 dirty = plLayerInterface::Eval(wSecs, frame, ignore);
	if (wSecs != fEvalTime)
	{
		UInt32 evalChans = 0;
		UInt32 passChans = dirty | fPassThruChannels;
		hsScalar oldAnimTime = fTimeConvert.CurrentAnimTime();
		hsScalar secs = oldAnimTime;
		
		if (fFadeFlagsDirty)
		{
			hsScalar goal = 0.f;

			if (fFadeFlags & kFadeLinkPrep)
				secs = goal = fLength;
			else
			{
				hsScalar rate = 0.f;
				hsScalar delta = (hsScalar)(wSecs - fEvalTime);
				
				if (fFadeFlags & kFadeLinking)
				{
					goal = fLength;
					rate = 1.f;
				}
				else if (fFadeFlags & kFadeCamera)
				{
					goal = fLength;
					rate = 10.f;
				}
				else if (fFadeFlags & (kFadeIFace | kFadeCCR))
				{
					goal = fLength * 0.4f;
					rate = 10.f;
				}
				else if (fFadeFlags == 0)
				{
					goal = 0.f;
					if (fLastFadeFlag == kFadeLinking)
						rate = 1.f;
					else
						rate = 10.f;
				}

				if (fabs(oldAnimTime - goal) < delta * rate || rate == 0)
					secs = goal;
				else if (goal > oldAnimTime)
					secs = oldAnimTime + delta * rate;
				else
					secs = oldAnimTime - delta * rate;
			}

			if (secs == goal)
				fFadeFlagsDirty = false;
		}
		
		if( secs != fCurrentTime )
		{
			fTimeConvert.SetCurrentAnimTime(secs);
			if (secs == 0.f || oldAnimTime == 0.f)
			{
				// Either we're going opaque, or we were opaque and now we're fading.
				// Tell the armature to re-eval its opacity settings.
				plAvatarOpacityCallbackMsg *opacityMsg = TRACKED_NEW plAvatarOpacityCallbackMsg(fLinkKey, kStop);
				opacityMsg->SetBCastFlag(plMessage::kPropagateToModifiers);
				opacityMsg->Send();
			}				
			evalChans = fOwnedChannels & ~ignore & ~fPassThruChannels;
			fCurrentTime = secs;
		}
		IEvalConvertedTime(secs, passChans, evalChans, dirty);
	}
	fEvalTime = wSecs;
	return dirty;
}

void plLayerLinkAnimation::SetFadeFlag(UInt8 flag, hsBool val)
{
	if (val)
		fFadeFlags |= flag;
	else
		fFadeFlags &= ~flag;

	if (fFadeFlags == 0)
		fLastFadeFlag = flag;
	
	TopOfStack()->Eval(hsTimer::GetSysSeconds(), 0, 0);
	ClaimChannels(fOwnedChannels);
	fCurrentTime = -1; // force eval
	fFadeFlagsDirty = true;
}

hsBool plLayerLinkAnimation::MsgReceive( plMessage* pMsg )
{
	plLinkEffectPrepBCMsg *bcpMsg = plLinkEffectPrepBCMsg::ConvertNoRef(pMsg);
	if (bcpMsg != nil)
	{
		if (bcpMsg->fLinkKey != fLinkKey || bcpMsg->fLeavingAge)
			return true;
	
		SetFadeFlag(kFadeLinkPrep, true);
		return true;
	}
		
		
	plLinkEffectBCMsg *msg = plLinkEffectBCMsg::ConvertNoRef(pMsg);
	if (msg != nil)
	{
		if (msg->fLinkKey == fLinkKey)
		{
			SetFadeFlag(kFadeLinkPrep, false);
			if (msg->HasLinkFlag(plLinkEffectBCMsg::kLeavingAge))
				SetFadeFlag(kFadeLinking, true);
			else
				SetFadeFlag(kFadeLinking, false);

			if (msg->HasLinkFlag(plLinkEffectBCMsg::kSendCallback))
			{
				plLinkEffectsMgr *mgr;
				if (mgr = plLinkEffectsMgr::ConvertNoRef(msg->GetSender()->ObjectIsLoaded()))
					mgr->WaitForEffect(msg->fLinkKey, fTimeConvert.GetEnd() - fTimeConvert.GetBegin());
			}			
		}
		return true;
	}

	plPseudoLinkAnimTriggerMsg* pSeudoMsg = plPseudoLinkAnimTriggerMsg::ConvertNoRef(pMsg);
	if (pSeudoMsg)
	{
		if (fLinkKey != pSeudoMsg->fAvatarKey)
			return true;

		if (pSeudoMsg->fForward)
			SetFadeFlag(kFadeLinking, true);
		else
			SetFadeFlag(kFadeLinking, false);
		
		// add a callback for when it's done if it's in forward
		plLinkEffectsMgr *mgr;
		if (mgr = plLinkEffectsMgr::ConvertNoRef(pMsg->GetSender()->ObjectIsLoaded()))
			if (pSeudoMsg->fForward)
				mgr->WaitForPseudoEffect(fLinkKey, fTimeConvert.GetEnd() - fTimeConvert.GetBegin());

		return true;
	}
	// used to fade the player in or out when entering / exiting first person mode
	// or when distance between camera and player is too small...
	plCameraTargetFadeMsg* fMsg = plCameraTargetFadeMsg::ConvertNoRef(pMsg);
	if (fMsg)
	{
		if (fLinkKey != fMsg->GetSubjectKey())
			return true;

		if (fMsg->FadeOut())
			SetFadeFlag(kFadeCamera, true);
		else
			SetFadeFlag(kFadeCamera, false);	

		return true;
	}
	plIfaceFadeAvatarMsg* iMsg = plIfaceFadeAvatarMsg::ConvertNoRef(pMsg);
	if (iMsg)
	{
		if (fLinkKey != iMsg->GetSubjectKey())
			return true;

		if (iMsg->GetEnable())
		{
			Enable(true);
		}
		else if (iMsg->GetDisable())
		{
			Enable(false); // disable and un-fade
			SetFadeFlag(kFadeIFace, false);
		}
		else
		if (fEnabled)
		{
			if (iMsg->FadeOut())
				SetFadeFlag(kFadeIFace, true);
			else
				SetFadeFlag(kFadeIFace, false);
		}
		return true;
	}

	plAvatarStealthModeMsg *sMsg = plAvatarStealthModeMsg::ConvertNoRef(pMsg);
	if (sMsg)
	{
		if (sMsg->GetSender() == fLinkKey)
		{
			if (sMsg->fMode == plAvatarStealthModeMsg::kStealthCloakedButSeen)
			{
				SetFadeFlag(kFadeCCR, true);
			}
			else if (sMsg->fMode == plAvatarStealthModeMsg::kStealthVisible)
			{
				SetFadeFlag(kFadeCCR, false);
			}
			// Don't need to set opacity if we're fully cloaked, since we won't
			// even be drawing the spans (due to plEnableMsg() on the sceneObject)
		}
		return true;
	}

	return plLayerAnimation::MsgReceive( pMsg );
}

///////////////////////////////////////////////////////////////////////////////////////////////

plLayerSDLAnimation::plLayerSDLAnimation() : plLayerAnimationBase(), fVar(nil), fVarName(nil) {}

plLayerSDLAnimation::~plLayerSDLAnimation()
{
	delete [] fVarName;
}

UInt32 plLayerSDLAnimation::Eval(double wSecs, UInt32 frame, UInt32 ignore)
{
	UInt32 dirty = plLayerInterface::Eval(wSecs, frame, ignore);
	if( wSecs != fEvalTime )
	{
		UInt32 evalChans = 0;
		UInt32 passChans = dirty | fPassThruChannels;

		if (fEvalTime < 0)
		{
			if (fVarName != nil)
			{
				extern const plSDLModifier *ExternFindAgeSDL();
				const plSDLModifier *sdlMod = ExternFindAgeSDL();
				if (sdlMod)
				{
					fVar = sdlMod->GetStateCache()->FindVar(fVarName);
					if (fVar)
						sdlMod->AddNotifyForVar(GetKey(), fVarName, 0);
				}
			}
		}
		hsScalar secs;
		if (fVar)
			fVar->Get(&secs);
		else
			secs = 0.f;

		// We're guaranteed a 0-1 time. Scale that to our animation length.
		secs *= GetLength();

		if( secs != fCurrentTime )
		{
			evalChans = fOwnedChannels & ~ignore & ~fPassThruChannels;
			fCurrentTime = secs;
		}

		IEvalConvertedTime(secs, passChans, evalChans, dirty);
	}
	fEvalTime = wSecs;
	return dirty;
}

hsBool plLayerSDLAnimation::MsgReceive(plMessage* msg)
{
	plSDLNotificationMsg* nMsg = plSDLNotificationMsg::ConvertNoRef(msg);
	if (nMsg)
	{
		TopOfStack()->Eval(hsTimer::GetSysSeconds(), 0, 0);
		ClaimChannels(fOwnedChannels);
		return true;
	}

	return plLayerAnimationBase::MsgReceive(msg);
}

void plLayerSDLAnimation::Read(hsStream* s, hsResMgr* mgr)
{
	plLayerAnimationBase::Read(s, mgr);

	fVarName = s->ReadSafeString();
}

void plLayerSDLAnimation::Write(hsStream* s, hsResMgr* mgr)
{
	plLayerAnimationBase::Write(s, mgr);

	s->WriteSafeString(fVarName);
}

void plLayerSDLAnimation::SetVarName(char *name) 
{ 
	delete [] fVarName; 
	fVarName = hsStrcpy(name); 
}