// AnimDetail.cpp : implementation file
//

#include "stdafx.h"
#include "AnimSize.h"
#include "AnimDetail.h"
#include "ChannelDump.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// AnimDetail dialog


AnimDetail::AnimDetail(const char *animation_name, CWnd* pParent /*=NULL*/)
	: CDialog(AnimDetail::IDD, pParent)
{
	//{{AFX_DATA_INIT(AnimDetail)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	animationName = animation_name;
	animData.Load(animation_name);
	
	iconList = new CImageList;
	Register_Pointer(iconList);

	iconList->Create(16,16, ILC_COLOR16, 2,2);

	iconList->Add( theApp.LoadIcon( IDI_ICON_POS ));
	iconList->Add( theApp.LoadIcon( IDI_ICON_ROT ));
	iconList->Add( theApp.LoadIcon( IDI_ICON_VEL ));
	iconList->Add( theApp.LoadIcon( IDI_ICON_TRG ));
	iconList->Add( theApp.LoadIcon( IDI_ICON_ANGVEL ));

}

AnimDetail::~AnimDetail()
{

	Unregister_Pointer(iconList);
	delete iconList;
	iconList = NULL;

}


void AnimDetail::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(AnimDetail)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(AnimDetail, CDialog)
	//{{AFX_MSG_MAP(AnimDetail)
	ON_BN_CLICKED(IDC_BUTTON_STREAM, OnButtonStream)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// AnimDetail message handlers

void AnimDetail::PostNcDestroy() 
{
	
	CDialog::PostNcDestroy();
	
	delete this;
}

BOOL AnimDetail::OnInitDialog() 
{
	CDialog::OnInitDialog();
	

	CListCtrl *list = (CListCtrl *)GetDlgItem( IDC_ANIM_DETAIL_LIST );
	list->InsertColumn( 0, "Joint", LVCFMT_LEFT, 150);
	list->InsertColumn( 1, "OneKeySize", LVCFMT_LEFT, 70);
	list->InsertColumn( 2, "KeyCount", LVCFMT_LEFT, 70);
	list->InsertColumn( 3, "TotalKeySize", LVCFMT_LEFT, 75);


	list->SetImageList(iconList, LVSIL_SMALL);

	int absolute_count = 0;

	for (int i = 0; i < animData.GetJointCount(); ++i)
	{

		Stuff::MString temp_name = animData.animJointBlock[i].GetName(animData.animNameBlock);

		Stuff::MString uncomp;


		MW4Animation::UncompressName(temp_name, uncomp);

		CString joint_name;
		joint_name = (const char *)uncomp;

		for (int chan_count = 0; chan_count < animData.animJointBlock[i].channelsUsed; chan_count++)
		{

			ChannelAnimData *cur_channel = &animData.animChannelBlock[animData.animJointBlock[i].firstChannel + chan_count];
			Check_Pointer(cur_channel);

			int item = 0;
			switch (cur_channel->keyType)
			{
				case JointAnimData::Point3DLinearKeyType:
						item = list->InsertItem( absolute_count, joint_name, 0 );
						break;
				case JointAnimData::QuaternionLinearKeyType:
						item = list->InsertItem( absolute_count, joint_name, 1 );
						break;
				case JointAnimData::VelocityLinearKeyType:
						item = list->InsertItem( absolute_count, joint_name, 2 );
						break;
				case JointAnimData::TriggerLinearKeyType:
						item = list->InsertItem( absolute_count, joint_name, 3 );
						break;
				case JointAnimData::AngularVelocityLinearKeyType:
						item = list->InsertItem( absolute_count, joint_name, 4 );
						break;
			}

			CString key_count_text;
			CString key_size_text;
			CString total_key_size_text;
			
			key_count_text.Format("%d", cur_channel->keyframeCount);
			key_size_text.Format("%d", cur_channel->sizeOfOneKey);
			total_key_size_text.Format("%d", cur_channel->sizeOfOneKey * cur_channel->keyframeCount);
			
			list->SetItemText( absolute_count, 1, key_size_text );
			list->SetItemText( absolute_count, 2, key_count_text );
			list->SetItemText( absolute_count, 3, total_key_size_text );

			++absolute_count;
		}

	}


	CEdit *edit;
	CString size_string;



	edit = (CEdit *)GetDlgItem( IDC_EDIT_LOAD_OVERHEAD );
	Check_Pointer(edit);
	size_string.Format("%d", sizeof(AnimData));
	edit->SetWindowText( size_string );


	edit = (CEdit *)GetDlgItem( IDC_EDIT_HEADER_SIZE );
	Check_Pointer(edit);
	size_string.Format("%d", animData.animHeaderBlockSize);
	edit->SetWindowText( size_string );

	
	edit = (CEdit *)GetDlgItem( IDC_EDIT_NAME_SIZE );
	Check_Pointer(edit);
	size_string.Format("%d", animData.animNameBlockSize);
	edit->SetWindowText( size_string );

	edit = (CEdit *)GetDlgItem( IDC_EDIT_KEYSIZE );
	Check_Pointer(edit);
	size_string.Format("%d", animData.animKeyBlockSize);
	edit->SetWindowText( size_string );


	edit = (CEdit *)GetDlgItem( IDC_EDIT_JOINT_SIZE );
	Check_Pointer(edit);
	size_string.Format("%d", animData.animJointBlockSize);
	edit->SetWindowText( size_string );


	edit = (CEdit *)GetDlgItem( IDC_EDIT4_CHANNEL_SIZE );
	Check_Pointer(edit);
	size_string.Format("%d", animData.animChannelBlockSize);
	edit->SetWindowText( size_string );

	
	edit = (CEdit *)GetDlgItem( IDC_EDIT_JOINT_COUNT );
	Check_Pointer(edit);
	size_string.Format("%d", animData.GetJointCount());
	edit->SetWindowText( size_string );


	edit = (CEdit *)GetDlgItem( IDC_EDIT_CHANNEL_COUNT );
	Check_Pointer(edit);
	size_string.Format("%d", animData.GetChannelCount());
	edit->SetWindowText( size_string );
	

	edit = (CEdit *)GetDlgItem( IDC_EDIT_TOTAL_SIZE );
	Check_Pointer(edit);
	size_string.Format("%d", animData.GetSize() + sizeof(AnimData));
	edit->SetWindowText( size_string );

	SetWindowText(animationName);	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

#define NEWLINE "\r\n"

void AnimDetail::OnButtonStream() 
{
	// view the raw data	



	CListCtrl *list = (CListCtrl *)GetDlgItem( IDC_ANIM_DETAIL_LIST );
	Check_Pointer(list);


	for (int i = 0; i < list->GetItemCount( ); ++i)
	{
		//if (list->GetCheck(i))
		if (list->GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
		{
			ChannelDump *dump_window;


			CString channel_data;
			DumpData(channel_data, i);


			dump_window = new ChannelDump(channel_data);

			dump_window->Create(IDD_CHAN_DUMP_DIALOG);
			dump_window->ShowWindow(SW_SHOW);
		}
	}





	
}


void AnimDetail::DumpData(CString &channel_data, int channel_number)
{
		
	ChannelAnimData *cur_channel = &animData.animChannelBlock[channel_number];
	Check_Pointer(cur_channel);

	switch (cur_channel->keyType)
	{
		case JointAnimData::Point3DLinearKeyType:
				channel_data += "Time\tX\tY\tZ";
				channel_data += NEWLINE;
				break;
		
			case JointAnimData::QuaternionLinearKeyType:
				channel_data += "Time\tX\tY\tZ\tW";
				channel_data += NEWLINE;
				break;
		
			case JointAnimData::TriggerLinearKeyType:
				channel_data += "Time\tvalue\t0-15";
				channel_data += NEWLINE;
				break;

			case JointAnimData::VelocityLinearKeyType:
				channel_data += "Time\tX\tY\tX\tXv\tYv\tZv";
				channel_data += NEWLINE;
				break;

			case JointAnimData::AngularVelocityLinearKeyType:
				channel_data += "Time\tX\tY\tZ\tW\tXv\tYv\tZv";
				channel_data += NEWLINE;
				break;

	}

	for (int keyframe = 0; keyframe < cur_channel->keyframeCount; keyframe++)
	{
		BaseKeyframe *base_keyframe = (BaseKeyframe *)
			((BYTE*)animData.animKeyBlock + cur_channel->offsetToKeyData + (cur_channel->sizeOfOneKey * keyframe));

		BaseKeyframeTime *base_keyframetime = (BaseKeyframeTime *)
			((BYTE*)animData.animKeyTimeBlock + cur_channel->offsetToKeyTimeData + (4 * keyframe));


		Check_Pointer(base_keyframe);

		CString time;
		time.Format("%.3f", base_keyframetime->timeOfFrame);
		channel_data += time;
		channel_data += " : \t";
		
		CString addon = "";
		switch (cur_channel->keyType)
		{
		
			case JointAnimData::Point3DLinearKeyType:
				addon.Format("%.3f\t%.3f\t%.3f",
					((Point3DLinearKey*)base_keyframe)->valueOfKey.x,
					((Point3DLinearKey*)base_keyframe)->valueOfKey.y,
					((Point3DLinearKey*)base_keyframe)->valueOfKey.z
				);
				break;
		
			case JointAnimData::QuaternionLinearKeyType:
				addon.Format("%.3f\t%.3f\t%.3f\t%.3f",
					((QuaternionLinearKey*)base_keyframe)->valueOfKey.x,
					((QuaternionLinearKey*)base_keyframe)->valueOfKey.y,
					((QuaternionLinearKey*)base_keyframe)->valueOfKey.z,
					((QuaternionLinearKey*)base_keyframe)->valueOfKey.w
				);

				break;
		
			case JointAnimData::TriggerLinearKeyType:
				{
					//((TriggerLinearKey*)base_keyframe)->value
					CString flag_string;
					flag_string.Format("%d\t\t", ((TriggerLinearKey*)base_keyframe)->valueOfKey);
					addon += flag_string;
					int temp = ((TriggerLinearKey*)base_keyframe)->valueOfKey;
					
					for (int i = 0; i < 16; ++i)
					{
						
						int flag = temp & 3;
						temp = temp >> 2;

						flag_string.Format("%d  ", flag);
						addon += flag_string;
					}
				}
				break;

			case JointAnimData::VelocityLinearKeyType:
				addon.Format("%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f",
					((VelocityLinearKey*)base_keyframe)->valueOfKey.x,
					((VelocityLinearKey*)base_keyframe)->valueOfKey.y,
					((VelocityLinearKey*)base_keyframe)->valueOfKey.z,
					((VelocityLinearKey*)base_keyframe)->velocityOfKey.x,
					((VelocityLinearKey*)base_keyframe)->velocityOfKey.y,
					((VelocityLinearKey*)base_keyframe)->velocityOfKey.z
				);
				break;

			case JointAnimData::AngularVelocityLinearKeyType:
				addon.Format("%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f",
					((AngularVelocityLinearKey*)base_keyframe)->valueOfKey.x,
					((AngularVelocityLinearKey*)base_keyframe)->valueOfKey.y,
					((AngularVelocityLinearKey*)base_keyframe)->valueOfKey.z,
					((AngularVelocityLinearKey*)base_keyframe)->valueOfKey.w,
					((AngularVelocityLinearKey*)base_keyframe)->velocityOfKey.x,
					((AngularVelocityLinearKey*)base_keyframe)->velocityOfKey.y,
					((AngularVelocityLinearKey*)base_keyframe)->velocityOfKey.z
				);

		}
		
		channel_data += addon;
		channel_data += NEWLINE;
	}

}



