// DisplayMngr.cpp: implementation of the CDisplayMngr class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DisplayMngr.h"
#include "6046dryenddlg.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDisplayMngr::CDisplayMngr()
{
	for(int i=0;i<MAX_DISPLAYS;i++)
		m_Displays[i] = NULL;

	m_bInitDone = FALSE;
}

CDisplayMngr::~CDisplayMngr()
{

}

//////////////////////////////////////////////////////////////////////

BOOL CDisplayMngr::LoadDisplays()
{
	bool err = FALSE;

	//Load Display Dialogs, index corresponds
	m_Displays[WFHIGH]		= new CDlgWaterfall;
	m_Displays[WFLOW]		= new CDlgWaterfall;
	m_Displays[WFSBP]		= new CDlgSBPDisplay;
	m_Displays[DSPATT]		= new CDlgTimeSeries;
	m_Displays[DSPDEPTH]	= new CDlgDepth;
	m_Displays[DSPCOMPASS]	= new CDlgCompass;
	m_Displays[DSPNAV]		= new CDlgNavText;
	m_Displays[DSPASCII]	= new CDlgTextOnly;
	m_Displays[DSPBATHY]		= new CBathyDisplay;
	m_Displays[DSPIMAGERY]		= new CDlgImagery;

	//check for load error
	for(int j = 0; j < MAX_DISPLAYS; j++)
	{

		if(m_Displays[j] == NULL)
		{	
			m_bInitDone = FALSE;
			return FALSE;
		}
	}
	
	((CDlgWaterfall*)m_Displays[WFHIGH])->SetType(WFHIGH);
	((CDlgWaterfall*)m_Displays[WFLOW])->SetType(WFLOW);
	((CDlgSBPDisplay*)m_Displays[WFSBP])->SetType(WFSBP);
	
	m_Displays[WFHIGH]->Create(IDD_DLG_WATERFALL, CWnd::GetDesktopWindow());
	m_Displays[WFLOW]->Create(IDD_DLG_WATERFALL, CWnd::GetDesktopWindow());
	m_Displays[WFSBP]->Create(IDD_DLG_SBP,		 CWnd::GetDesktopWindow());
	
	m_Displays[DSPATT]->Create(IDD_DLG_TIMESERIES, CWnd::GetDesktopWindow());
	m_Displays[DSPDEPTH]->Create(IDD_DLG_DEPTH, CWnd::GetDesktopWindow());
	m_Displays[DSPCOMPASS]->Create(IDD_DLG_HEADING, CWnd::GetDesktopWindow());
	m_Displays[DSPNAV]->Create(IDD_DLG_NAVTEXT, CWnd::GetDesktopWindow());
	m_Displays[DSPASCII]->Create(IDD_DLG_TEXTONLY, CWnd::GetDesktopWindow());
	m_Displays[DSPBATHY]->Create(IDD_DLG_BATHY, CWnd::GetDesktopWindow());
	m_Displays[DSPIMAGERY]->Create(IDD_DLG_IMAGERY, CWnd::GetDesktopWindow());
  

	m_Displays[WFHIGH]->SetWindowText("High Frequency Side Scan Display");
	m_Displays[WFLOW]->SetWindowText("Low Frequency Side Scan Display");
	m_Displays[WFSBP]->SetWindowText("Sub Bottom Profiler Display");
	m_Displays[DSPATT]->SetWindowText("Attitude Time Series Display");

	m_pConfig = &((CMy6046DryEndApp*)AfxGetApp())->m_SystemConfig;

	LoadSettings();

	m_bInitDone = TRUE;

	return err;

}

BOOL CDisplayMngr::InitWindows()
{
	BOOL err = FALSE;

	return err;
}

BOOL CDisplayMngr::Init()
{
	return m_bInitDone;
}


//////////////////////////////////////////////////////////////////////

void CDisplayMngr::ShowDisplay(DISPLAY_TYPE etype)
{
	m_Displays[etype]->ShowWindow(SW_SHOW);
}

void CDisplayMngr::HideDisplay(DISPLAY_TYPE etype)
{
    m_Displays[etype]->ShowWindow(SW_HIDE);
}

void CDisplayMngr::BringToTop()
{
	CMy6046DryEndDlg *me = ((CMy6046DryEndDlg*)AfxGetMainWnd());
	for(int i =0; i<MAX_DISPLAYS; i++)
	{
		if(m_Displays[i] && m_Displays[i]->m_hWnd)
		{
			switch(i)
			{
			case WFHIGH:{ if(me->m_bWaterfallHIGH)
							BringAndShow(i);
						  break;
						}
			case WFLOW: { if(me->m_bWaterfallLOW)
							BringAndShow(i);
						  break;
						}
			case WFSBP:{ if(me->m_bWaterfallSBP)
							BringAndShow(i);
						  break;
						}
			case DSPATT: { if(me->m_bAttitude)
							BringAndShow(i);
						  break;
						}
			case DSPDEPTH: { if(me->m_bDepth)
							BringAndShow(i);
						  break;
						}
			case DSPCOMPASS: { if(me->m_bHeading)
							BringAndShow(i);
						  break;
						}
			case DSPNAV: { if(me->m_bNav)
							BringAndShow(i);
						  break;
						}
			case DSPASCII: { if(me->m_bTextOnly)
							BringAndShow(i);
						  break;
						}
			case DSPBATHY: { if(me->m_bBathy)
							BringAndShow(i);
						  break;
						}
			case DSPIMAGERY:{ if(me->m_bImagery)
							BringAndShow(i);
						  break;
						}
			}
			
		}
	}
}

void CDisplayMngr::BringAndShow( int displayIndex )
{
	m_Displays[displayIndex]->BringWindowToTop();
	m_Displays[displayIndex]->ShowWindow(SW_RESTORE);
}



void CDisplayMngr::MinimizeAll()
{
	CMy6046DryEndDlg *me = ((CMy6046DryEndDlg*)AfxGetMainWnd());
	for(int i =0; i<MAX_DISPLAYS; i++)
	{
		if(m_Displays[i] && m_Displays[i]->m_hWnd)
		{
			switch(i)
			{
			case WFHIGH:{ if(me->m_bWaterfallHIGH)
							m_Displays[i]->ShowWindow(SW_MINIMIZE);
						  break;
						}
			case WFLOW: { if(me->m_bWaterfallLOW)
							m_Displays[i]->ShowWindow(SW_MINIMIZE);
						  break;
						}
			case WFSBP:{ if(me->m_bWaterfallSBP)
							m_Displays[i]->ShowWindow(SW_MINIMIZE);
						  break;
						}
			case DSPATT: { if(me->m_bAttitude)
							m_Displays[i]->ShowWindow(SW_MINIMIZE);
						  break;
						}
			case DSPDEPTH: { if(me->m_bDepth)
								m_Displays[i]->ShowWindow(SW_MINIMIZE);
							 break;
						}
			case DSPCOMPASS: { if(me->m_bHeading)
								 m_Displays[i]->ShowWindow(SW_MINIMIZE);
							   break;
						}
			case DSPNAV: { if(me->m_bNav)
							m_Displays[i]->ShowWindow(SW_MINIMIZE);
						
							break;
						}
			case DSPASCII: { if(me->m_bTextOnly)
								m_Displays[i]->ShowWindow(SW_MINIMIZE);
							break;
						}
			case DSPBATHY: { if(me->m_bBathy)
								m_Displays[i]->ShowWindow(SW_MINIMIZE);
							break;
						}
			case DSPIMAGERY:{ if(me->m_bImagery)
								m_Displays[i]->ShowWindow(SW_MINIMIZE);
							  break;
						}
			}
			
		}
			
	}
}


void CDisplayMngr::SendToBottom()
{
	for(int i =0; i<MAX_DISPLAYS; i++)
	{
		//if(m_Displays[i])
		//	m_Displays[i]->
	}
}

//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//START DATA UPDATE FUNCTIONS
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////


void CDisplayMngr::AddGroupData( NBlueFin7kMessages::PBLUEFINRECORDTYPEHEADER	 pRecHdr,
								 NBlueFin7kMessages::PBLUEFINNETWORKHEADER		 pNetHdr,
								 NBlueFin7kMessages::PBLUEFINNAVIGATIONMESSAGE   pNavFrame )
{

	((CDlgTimeSeries*)m_Displays[DSPATT])->AddGroup( pRecHdr, pNavFrame );
	
	((CDlgDepth*)m_Displays[DSPDEPTH])->AddGroupData(pRecHdr, pNavFrame);
	
	((CDlgNavText*)m_Displays[DSPNAV])->AddGroupData( pRecHdr, pNetHdr, pNavFrame );
	
	((CDlgCompass*)m_Displays[DSPCOMPASS])->AddGroupData( pRecHdr, pNavFrame );
	
	((CDlgTextOnly*)m_Displays[DSPASCII])->AddGroupData( pRecHdr, pNavFrame );
}

void CDisplayMngr::AddRoll(float roll)
{
	//((CDlgTimeSeries*)m_Displays[3])->AddRoll(roll);
}

void CDisplayMngr::AddPitch(float pitch)
{
	//((CDlgTimeSeries*)m_Displays[3])->AddPitch(pitch);
}

void CDisplayMngr::AddHeave(float heave)
{

}

void CDisplayMngr::AddDepth(float depth)
{
	//((CDlgDepth*)m_Displays[4])->AddDepth(depth);
}

void CDisplayMngr::AddHeading(float heading)
{

}

//DEBUG
/*
BOOL CDisplayMngr::AddSSSData(BYTE *data, int size)
{
	((CDlgWaterfall*)m_Displays[0])->AddNewProfile(data, size);
	((CDlgSBPDisplay*)m_Displays[2])->AddNewProfile(data, size);
	return TRUE;
	
}
*/

//
BOOL CDisplayMngr::AddWaterfallData(DISPLAY_TYPE type, BYTE *data, int size)
{
	switch(type)
	{
	case WFHIGH: ((CDlgWaterfall*)m_Displays[WFHIGH])->AddNewProfile(data, size); break;
	case WFLOW:  ((CDlgWaterfall*)m_Displays[WFLOW])->AddNewProfile(data, size);break;
	case WFSBP:  ((CDlgSBPDisplay*)m_Displays[WFSBP])->AddNewProfile(data, size);break;
	}
		
	return TRUE;
}

void CDisplayMngr::SetWaterfallParams(DISPLAY_TYPE type, SETTINGS *settings)
{
	CString message;

	if(type == WFSBP)
	{
		message.Format("Sub Bottom Profiler      Power = %d, Gain = %d, Ping Period = %.0f ms", settings->power, settings->gain, settings->duration);
		((CDlgSBPDisplay*)m_Displays[WFSBP])->SetWindowText(message);
	}
	else if(type == WFHIGH)
	{
		message.Format("SSS HF    Range = %dm", settings->range);
		((CDlgWaterfall*)m_Displays[type])->SetWindowText(message);
	}
	else if(type == WFLOW)
	{
		message.Format("SSS LF    Range = %dm", settings->range);
		((CDlgWaterfall*)m_Displays[type])->SetWindowText(message);
	}
}

void CDisplayMngr::AddBathyData( void *dataBytes )
{
	R7006* bathy = (R7006*)dataBytes;
	
	((CBathyDisplay*)m_Displays[DSPBATHY])->AddBathyData(dataBytes);

	((CDlgImagery*)m_Displays[DSPIMAGERY])->m_dispWedge.SetBathyData(((BYTE*)dataBytes) + sizeof(R7006), m_rec7000.sound_velocity);

}

void CDisplayMngr::AddImageryData(void *dataBytes )
{
	R7011* temp = (R7011*)dataBytes;
	BYTE* data = ((BYTE*)dataBytes) + sizeof(R7011);

	((CDlgImagery*)m_Displays[DSPIMAGERY])->m_dispWedge.SetData(data, temp->width, temp->height);
}

void CDisplayMngr::RelayBeamGeometry(	BYTE *dataBytes )
{
	DWORD beams;
	float first, last, swath;
	R7004 * r7004;
 
    DWORD startpos = 0;
    DWORD endpos = 0;
    DWORD uniformspacing = 0; // should stay zero if we have uniform sapcing

    r7004 = (R7004*) dataBytes;
   
    beams = r7004->beams;
    first = *(float*) (dataBytes + sizeof(R7004) + beams*sizeof(float));
    last  = *(float*) (dataBytes + sizeof(R7004) + beams*sizeof(float) + (beams-1)*sizeof(float));
  
    // See if we have non uniform spacing
    if(first == 0)
	{
	  DWORD i;
	  for(i = 0; i < beams; i++)
	  { 
		if(*(float*) (dataBytes + sizeof(R7004) + beams*sizeof(float) + i*sizeof(float)) != 0)
		{
			startpos = i;
			first = *(float*) (dataBytes + sizeof(R7004) + beams*sizeof(float) + i*sizeof(float));
			break;
		}
	  }
	  for(i = startpos; i < beams; i++)
	  {
		if((*(float*) (dataBytes + sizeof(R7004) + beams*sizeof(float) + i*sizeof(float)) == 0) && (i > beams/2 + 2))
		{
			endpos = i - 1;
			last = *(float*) (dataBytes + sizeof(R7004) + beams*sizeof(float) + (i-1)*sizeof(float));
			break;
		}
	  }
	  uniformspacing = endpos - startpos + 1;
	}

  
    if(first < last)
	{
      swath = (first + (2*PI - last));
	}
    else
	{
      swath = (first - last);
	}

    // Add half of first and last beam width.
    swath += (*(float*) (dataBytes + sizeof(R7004) + beams*sizeof(float) * 3)) * 0.5;
    swath += (*(float*) (dataBytes + sizeof(R7004) + beams*sizeof(float) * 3 + (beams-1)*sizeof(float))) * 0.5;

    ((CDlgImagery*)m_Displays[DSPIMAGERY])->m_dispWedge.SetWedgeGeometry(beams, first, last, (float*)(dataBytes + sizeof(R7004) + beams*sizeof(float)), uniformspacing);

}

void CDisplayMngr::Add7000Data(void *dataBytes )
{
	R7000 *info = (R7000*)dataBytes;

	memcpy(&m_rec7000, (BYTE*)dataBytes, sizeof(R7000));

	((CBathyDisplay*)m_Displays[DSPBATHY])->SetSoundVelocity(info->sound_velocity);

	((CDlgImagery*)m_Displays[DSPIMAGERY])->m_dispWedge.SetRange(info->range);
	
}

void CDisplayMngr::FlipDisplayedData(	BOOL bFlip )
{
	//Flip the wedge
	((CDlgImagery*)m_Displays[DSPIMAGERY])->m_dispWedge.SetFlip(bFlip);

	//Flip the scrolling bathy
	((CBathyDisplay*)m_Displays[DSPBATHY])->SetFlip(bFlip);
}

void CDisplayMngr::SetBeamSpacing(double beamSpacing )
{
	((CBathyDisplay*)m_Displays[DSPBATHY])->SetBeamSpacing(beamSpacing);
}


//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

void CDisplayMngr::Cleanup()
{
	SaveSettings();

	for(int i=0; i < MAX_DISPLAYS; i++)
	{
		switch(i)
		{
		case WFHIGH: ((CDlgWaterfall*)m_Displays[WFHIGH])->Cleanup(); break;
		case WFLOW:  ((CDlgWaterfall*)m_Displays[WFLOW])->Cleanup();break;
		case WFSBP:  ((CDlgSBPDisplay*)m_Displays[WFSBP])->Cleanup();break;
		}
		m_Displays[i]->DestroyWindow();
		delete m_Displays[i];		
		m_Displays[i] = NULL;
	}
}


void CDisplayMngr::LoadSettings()
{
	//All this is now moved to the windows

	
	//int x,y;
	//int cx,cy;
	//x = y = cx = cy = 0;

	//if(m_pConfig->Open(CSystemConfig::accessRead))
	//{
	//	m_pConfig->Read();
	//	m_pConfig->Close();
	//}
	
	//Get Attitude window pos
	//x	= m_pConfig->TSWindowX;
	//y	= m_pConfig->TSWindowY;
	//((CDlgTimeSeries*)m_Displays[DSPATT])->SetWindowPos(NULL,x,y,cx,cy,SWP_NOSIZE);

	//Get Depth window pos
	//x	= m_pConfig->DEPWindowX;
	//y	= m_pConfig->DEPWindowY;
	//((CDlgDepth*)m_Displays[DSPDEPTH])->SetWindowPos(NULL,x,y,cx,cy,SWP_NOSIZE);

	//Get Attitude window pos
	//x	= m_pConfig->HEDWindowX;
	//y	= m_pConfig->HEDWindowY;
	//((CDlgCompass*)m_Displays[DSPCOMPASS])->SetWindowPos(NULL,x,y,0,0,SWP_NOSIZE);

	//Get Nav window pos
	//x	= m_pConfig->NAVWindowX;
	//y	= m_pConfig->NAVWindowY;
	//((CDlgNavText*)m_Displays[DSPNAV])->SetWindowPos(NULL,x,y,0,0,SWP_NOSIZE);

	//Get ASCII window pos
	//x	= m_pConfig->ASCIWindowX;
	//y	= m_pConfig->ASCIWindowY;
	//((CDlgTextOnly*)m_Displays[DSPASCII])->SetWindowPos(NULL,x,y,0,0,SWP_NOSIZE);


}

void CDisplayMngr::SaveSettings()
{
	//All this is now moved to the windows
	
	//CRect wndRect;

	//SAVE TIMESERIES
	//((CDlgTimeSeries*)m_Displays[DSPATT])->GetWindowRect(&wndRect);
	//m_pConfig->TSWindowX	= wndRect.left;
	//m_pConfig->TSWindowY	= wndRect.top;

	//SAVE DEPTH
	//((CDlgDepth*)m_Displays[DSPDEPTH])->GetWindowRect(&wndRect);
	//m_pConfig->DEPWindowX	= wndRect.left;
	//m_pConfig->DEPWindowY	= wndRect.top;

	//SAVE HEADING
	//((CDlgCompass*)m_Displays[DSPCOMPASS])->GetWindowRect(&wndRect);
	//m_pConfig->HEDWindowX	= wndRect.left;
	//m_pConfig->HEDWindowY	= wndRect.top;

	//SAVE NAV
	//((CDlgNavText*)m_Displays[DSPNAV])->GetWindowRect(&wndRect);
	//m_pConfig->NAVWindowX	= wndRect.left;
	//m_pConfig->NAVWindowY	= wndRect.top;
	
	//SAVE ASCII
	//((CDlgTextOnly*)m_Displays[DSPASCII])->GetWindowRect(&wndRect);
	//m_pConfig->ASCIWindowX	= wndRect.left;
	//m_pConfig->ASCIWindowY	= wndRect.top;

}
