// PlotsDialog.cpp : implementation file
//

#include "stdafx.h"
#include "ZhengModelHeaders.h"

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

/////////////////////////////////////////////////////////////////////////////
// CPlotsDialog dialog

IMPLEMENT_SERIAL(CPlotsDialog, CDialog, _VERSION_NUMBER)

CPen* CPlotsDialog::m_pPenArray[NUM_PEN];


CPlotsDialog::CPlotsDialog(CWnd* pParent /*=NULL*/)
	: CDialog(CPlotsDialog::IDD, pParent)
{
	m_rect = CRect(0,0,0,0);
	for (int i=0; i < _MAX_PLOTS; i++) 
		m_rectPlot[i] = CRect(0,0,0,0);
	m_pPenArray[0] = new CPen(PS_SOLID, 1, RED);
	m_pPenArray[1] = new CPen(PS_SOLID, 1, GREEN);
	m_pPenArray[2] = new CPen(PS_SOLID, 1, BLUE);
	m_pPenArray[3] = new CPen(PS_SOLID, 1, VIOLET);
	m_pPenArray[4] = new CPen(PS_SOLID, 1, ORANGE);
	m_pPenArray[5] = new CPen(PS_SOLID, 1, BABY_BLUE);
	m_pPenArray[6] = new CPen(PS_SOLID, 1, YELLOW);
	m_pPenArray[7] = new CPen(PS_DOT, 1, GRAY);
	m_NumPlots = _MAX_PLOTS; 
	m_PlotHeight = 0;
	m_PlotWidth = 0;
	m_screen_num = -1;
	m_screen_num_old = -1;
	m_ZeroX = 0;
	m_LastX = 0;
	for (i=0; i < _MAX_PLOTS; i++) {
		m_minY[i] = _MINY;
		m_maxY[i] = _MAXY;
		m_BottomY[i] = 0;
		//m_ZeroY[i] = 0;
		m_LastY[i] = 0;
	}
	//{{AFX_DATA_INIT(CPlotsDialog)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}

CPlotsDialog::~CPlotsDialog() 
{
	for (int i = 0; i < NUM_PEN; i++) 
		delete m_pPenArray[i];
}

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


BEGIN_MESSAGE_MAP(CPlotsDialog, CDialog)
	//{{AFX_MSG_MAP(CPlotsDialog)
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPlotsDialog message handlers

BOOL CPlotsDialog::RestoreWindowState()
{
	CString version = "Version 1.0";

	WINDOWPLACEMENT wp;
	wp.length = sizeof(WINDOWPLACEMENT);
	GetWindowPlacement(&wp);

	if (((wp.rcNormalPosition.left = 
			AfxGetApp()->GetProfileInt (version, "Plots.x1", -1)) != -1) &&
		((wp.rcNormalPosition.top = 
			AfxGetApp()->GetProfileInt (version, "Plots.y1", -1)) != -1) &&
		((wp.rcNormalPosition.right = 
			AfxGetApp()->GetProfileInt (version, "Plots.x2", -1)) != -1) &&
		((wp.rcNormalPosition.bottom = 
			AfxGetApp()->GetProfileInt (version, "Plots.y2", -1)) != -1)) {

		wp.rcNormalPosition.left = min(wp.rcNormalPosition.left,
			::GetSystemMetrics(SM_CXSCREEN) - 
			::GetSystemMetrics(SM_CXICON));
		wp.rcNormalPosition.top = min (wp.rcNormalPosition.top,
			::GetSystemMetrics(SM_CYSCREEN) -
			::GetSystemMetrics(SM_CYICON));

		SetWindowPlacement (&wp);
		ClearPlots();
		return TRUE;
	}
	return FALSE;
}

void CPlotsDialog::SaveWindowState()
{
	CString version = "Version 1.0";

	WINDOWPLACEMENT wp;
	wp.length = sizeof(WINDOWPLACEMENT);
	GetWindowPlacement(&wp);

	AfxGetApp()->WriteProfileInt (version,"Plots.x1",wp.rcNormalPosition.left);
	AfxGetApp()->WriteProfileInt (version,"Plots.y1",wp.rcNormalPosition.top);
	AfxGetApp()->WriteProfileInt (version,"Plots.x2",wp.rcNormalPosition.right);
	AfxGetApp()->WriteProfileInt (version,"Plots.y2",wp.rcNormalPosition.bottom);
}

BOOL CPlotsDialog::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	//ClearPlots();
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CPlotsDialog::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	if (IsWindowVisible()) 
	{
		ClearPlots();
	}
	
}

/*void CPlotsDialog::DoPlots(int t_step, int num_steps_per_screen, int graph_frequency)
{
	//CDC* PlotsDC = ctrlPlotsPict().GetDC();
	CClientDC PlotsDC(&(ctrlPlotsPict()));
	//do x values, i.e. time, for all plot
	int T = t_step%num_steps_per_screen;
	int ThisX = (m_ZeroX + (int)(((double)T/num_steps_per_screen)*m_PlotWidth));
	if (T == 0) {
		ClearPlots();
		m_LastX = ThisX;
	}
	//do y values for each plot
	int ThisY[_MAX_PLOTS];  //actual y-value in picture box coordinates
	double YValue[_MAX_PLOTS]; //value of y as fraction of axis height
	double YVariable[_MAX_PLOTS]; //actual value of Y variable, in appropriate units for plotting
	double VSoma = GetCompart(_Soma)->m_V;
	YVariable[0] = VSoma; //Soma voltage [mV]
	YVariable[1] = GetCompart(_Hillock)->m_V; //Hillock voltage [mV]
	YVariable[2] = GetDoc()->m_IInject[_Soma]; //Soma current injection [nA]
	YVariable[3] = GetChan(_Soma, _I_CaT)->m_I(VSoma); //Soma CaT current
	YVariable[4] = GetChan(_Hillock, _I_Na)->m_gMax; //gMax for _I_Na
	YVariable[5] = GetChan(_Soma, _I_CaT)->m_gMax; //gMax for _I_CaT
	//YVariable[5] = GetCompart(_Soma)->m_ITotal(InjSoma); //Total current (in or out???) of soma [nA]
	for (int i = 0; i < m_NumPlots; i++) {
		YValue[i] = (YVariable[i] - m_minY[i])/(m_maxY[i] - m_minY[i]);
	}
	for (i = 0; i < m_NumPlots; i++) {
		PlotsDC.SelectObject(m_pPenArray[i]);
		ThisY[i] = (m_BottomY[i] - (int)(YValue[i]*m_PlotHeight));
		//ThisY[i] = (m_ZeroY[i] - (int)(YValue[i]*0.5*m_PlotHeight));
		if (T == 0) {
			m_LastY[i] = ThisY[i];
		}
		PlotsDC.MoveTo(m_LastX, m_LastY[i]);
		PlotsDC.LineTo(ThisX, ThisY[i]);
		m_LastY[i] = ThisY[i];
	}
	m_LastX = ThisX;
}*/

void CPlotsDialog::DoPlots(double t)
{
	//CDC* PlotsDC = ctrlPlotsPict().GetDC();
	CClientDC PlotsDC(&(ctrlPlotsPict()));
	//do x values, i.e. time, for all plots
	m_screen_num = (int)(t/_TIME_PER_SCREEN);  //start count at 0
	double T;
	int ThisX;
	T = t - (((double)m_screen_num) * _TIME_PER_SCREEN);
	ThisX = (m_ZeroX + (int)((T/_TIME_PER_SCREEN) * m_PlotWidth));
	if ((t == 0) OR (m_screen_num != m_screen_num_old)) {
		ClearPlots();
		m_LastX = ThisX;
		m_screen_num_old = m_screen_num;
	}
	//do y values for each plot
	int ThisY[_MAX_PLOTS];  //actual y-value in picture box coordinates
	double YValue[_MAX_PLOTS]; //value of y as fraction of axis height
	double YVariable[_MAX_PLOTS]; //actual value of Y variable, in appropriate units for plotting
	double VSoma = GetCompart(_Soma)->m_V;
	YVariable[0] = VSoma; //Soma voltage [mV]
	YVariable[1] = GetChan(_Soma, _I_CaT)->m_g(); //gMax for _I_CaT
	//YVariable[1] = GetCompart(_Hillock)->m_V; //Hillock voltage [mV]
	//YVariable[2] = GetDoc()->m_IInject[_Soma]; //Soma current injection [nA]
	//YVariable[2] = GetDoc()->m_dt;
	YVariable[2] = GetCompart(_Soma)->m_Ca;
	YVariable[3] = GetChan(_Soma, _I_KCa)->m_g(); //gMax for _I_CaT
	//YVariable[3] = GetChan(_Soma, _I_CaT)->m_I(VSoma); //Soma CaT current
	//YVariable[4] = GetChan(_Hillock, _I_Na)->m_gMax; //gMax for _I_Na
	YVariable[4] = GetDoc()->m_IInject[_Soma];
	//YVariable[5] = GetChan(_Soma, _I_KCa)->m_gMax; //gMax for _I_CaT
	//YVariable[5] = GetCompart(_Soma)->m_ITotal(InjSoma); //Total current (in or out???) of soma [nA]
	for (int i = 0; i < m_NumPlots; i++) {
		YValue[i] = (YVariable[i] - m_minY[i])/(m_maxY[i] - m_minY[i]);
	}
	for (i = 0; i < m_NumPlots; i++) {
		PlotsDC.SelectObject(m_pPenArray[i]);
		ThisY[i] = (m_BottomY[i] - (int)(YValue[i]*m_PlotHeight));
		//ThisY[i] = (m_ZeroY[i] - (int)(YValue[i]*0.5*m_PlotHeight));
		if (T == 0) {
			m_LastY[i] = ThisY[i];
		}
		PlotsDC.MoveTo(m_LastX, m_LastY[i]);
		PlotsDC.LineTo(ThisX, ThisY[i]);
		//PlotsDC.Ellipse(ThisX-3, ThisY[i]-3, ThisX+3, ThisY[i]+3);
		m_LastY[i] = ThisY[i];
	}
	m_LastX = ThisX;
}


void CPlotsDialog::ClearPlots()
{
	FitPictToFrame();
	//Clear screen
	//CDC* PlotsDC = ctrlPlotsPict().GetDC();
	CClientDC PlotsDC(&(ctrlPlotsPict()));
	PlotsDC.SelectStockObject(WHITE_BRUSH);
	PlotsDC.Rectangle(m_rect.left, m_rect.top, m_rect.right, m_rect.bottom);
	//draw axes and time label
	CRect LabelRect;
	char str[50];
	for (int i = 0; i < m_NumPlots; i++) {
		//draw labels
		LabelRect.left = 0;
		LabelRect.top = m_rectPlot[i].bottom;
		LabelRect.right = m_rectPlot[i].right;
		LabelRect.bottom = (m_rectPlot[i].bottom + (int)(BOTTOM_MARGIN*m_rect.bottom));
		sprintf(str, "%g msec", ((double)m_screen_num + 1)*_TIME_PER_SCREEN);		
		PlotsDC.DrawText(str, LabelRect, DT_RIGHT);
		LabelRect.left = 0;
		LabelRect.top = (int)(m_rectPlot[i].bottom - 0.5*TEXT_HEIGHT);
		LabelRect.right = m_rectPlot[i].left;
		LabelRect.bottom = (int)(m_rectPlot[i].bottom + 0.5*TEXT_HEIGHT);
		sprintf(str, "%g", m_minY[i]);
		PlotsDC.DrawText(str, LabelRect, DT_RIGHT);
		LabelRect.left = 0;
		LabelRect.top = (int)(m_rectPlot[i].top - 0.5*TEXT_HEIGHT);
		LabelRect.right = m_rectPlot[i].left;
		LabelRect.bottom = (int)(m_rectPlot[i].top + 0.5*TEXT_HEIGHT);
		sprintf(str, "%g", m_maxY[i]);
		PlotsDC.DrawText(str, LabelRect, DT_RIGHT);
		//Calculate ranges for y's


		//draw axes
		PlotsDC.SelectObject(m_pPenArray[GRAY_PEN]);
		for (int j = 0; j < NUM_VERT_SECT; j++) {
			PlotsDC.MoveTo(m_rectPlot[i].left, m_rectPlot[i].top + (int)(((double)j/NUM_VERT_SECT)*m_PlotHeight));
			PlotsDC.LineTo(m_rectPlot[i].right, m_rectPlot[i].top + (int)(((double)j/NUM_VERT_SECT)*m_PlotHeight));
		}
		for (j = 0; j < NUM_HORIZ_SECT; j++) {
			PlotsDC.MoveTo(m_rectPlot[i].left + (int)(((double)j/NUM_HORIZ_SECT)*m_PlotWidth), m_rectPlot[i].top);
			PlotsDC.LineTo(m_rectPlot[i].left + (int)(((double)j/NUM_HORIZ_SECT)*m_PlotWidth), m_rectPlot[i].bottom);
		}
		PlotsDC.SelectStockObject(BLACK_PEN);
		//PlotsDC.MoveTo(m_rectPlot[i].left, m_ZeroY[i]);
		//PlotsDC.LineTo(m_rectPlot[i].right, m_ZeroY[i]);
		PlotsDC.MoveTo(m_rectPlot[i].left, m_rectPlot[i].top);
		PlotsDC.LineTo(m_rectPlot[i].left, m_rectPlot[i].bottom);
		PlotsDC.LineTo(m_rectPlot[i].right, m_rectPlot[i].bottom);
		PlotsDC.LineTo(m_rectPlot[i].right, m_rectPlot[i].top);
		PlotsDC.LineTo(m_rectPlot[i].left, m_rectPlot[i].top);
	}
}

void CPlotsDialog::FitPictToFrame()
{
	//size picture box to size of dialog box
	GetClientRect(&m_rect);
	ctrlPlotsPict().SetWindowPos(&wndTop, (int)(0.02*m_rect.right), (int)(0.02*m_rect.bottom),
				(int)(0.96*m_rect.right), (int)(0.96*m_rect.bottom), SWP_NOZORDER);
	UpdateWindow();
	
	//size areas where the individual plots will appear
	ctrlPlotsPict().GetClientRect(&m_rect);
	m_PlotHeight = (int)((((1. - TOP_MARGIN)/((double)m_NumPlots)) - BOTTOM_MARGIN)*m_rect.bottom);
	m_PlotWidth = (int)((1. - RIGHT_MARGIN - LEFT_MARGIN) * m_rect.right);
	for (int i = 0; i < m_NumPlots; i++) {
		m_rectPlot[i].left = (int)(LEFT_MARGIN * m_rect.right);
		m_rectPlot[i].right = (m_rectPlot[i].left + m_PlotWidth);
		m_rectPlot[i].top = (int)(TOP_MARGIN*m_rect.bottom + 
							(i*(m_PlotHeight + (BOTTOM_MARGIN*m_rect.bottom))));
		m_rectPlot[i].bottom = (m_rectPlot[i].top + m_PlotHeight);
		m_BottomY[i] = m_rectPlot[i].bottom;
		//m_ZeroY[i] = (m_rectPlot[i].top + (int)(0.5*m_PlotHeight));
	}
	m_ZeroX = m_rectPlot[0].left;
}

/////////////////////////////////////////////////////////////////////////////
// CPlotsDialog serialization

void CPlotsDialog::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		ar << m_rect;
		for (int i=0; i < _MAX_PLOTS; i++) 
			ar << m_rectPlot[i];	
		ar << m_NumPlots; 
		ar << m_PlotHeight;
		ar << m_PlotWidth;
		ar << m_screen_num;
		ar << m_screen_num_old;
		ar << m_ZeroX;
		ar << m_LastX;
		for (i=0; i < _MAX_PLOTS; i++) {
			ar << m_minY[i];
			ar << m_maxY[i];
			ar << m_BottomY[i];
			ar << m_LastY[i];
		}	
	}	
	else
	{
		ar >> m_rect;
		for (int i=0; i < _MAX_PLOTS; i++) 
			ar >> m_rectPlot[i];	
		ar >> m_NumPlots; 
		ar >> m_PlotHeight;
		ar >> m_PlotWidth;
		ar >> m_screen_num;
		ar >> m_screen_num_old;
		ar >> m_ZeroX;
		ar >> m_LastX;
		for (i=0; i < _MAX_PLOTS; i++) {
			ar >> m_minY[i];
			ar >> m_maxY[i];
			ar >> m_BottomY[i];
			ar >> m_LastY[i];
		}			
	}
}