// BemInpView.cpp : implementation of the CBemInpView class
//

#include "stdafx.h"
#include "afxpriv.h"    // For WM_SETMESSAGESTRING
#include "BemInp.h"
#include "mainfrm.h"
#include "ZoomView.h"

#include "geom.h"
#include "BemInpDoc.h"
#include "BemInpView.h"
#include "boundial.h"
#include "addwell.h"

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

#define ND_MOVE 1
#define ND_ADD  2
#define ND_DEL  3
#define EL_ADD  4
#define EL_ALL  5
#define EL_DEL  6
#define IN_MOVE 7
#define IN_ADD  8
#define IN_DEL  9
#define BO_NEW  10
#define BO_EDIT  11
#define WL_MOVE 12
#define WL_ADD  13
#define WL_DEL  14
#define WL_EDIT  15

/////////////////////////////////////////////////////////////////////////////
// CBemInpView

IMPLEMENT_DYNCREATE(CBemInpView, CZoomView)

BEGIN_MESSAGE_MAP(CBemInpView, CZoomView)
	//{{AFX_MSG_MAP(CBemInpView)
	ON_COMMAND(ID_GEOM_NODE_ADD, OnNodeAdd)
	ON_COMMAND(ID_GEOM_NODE_DELETE, OnNodeDelete)
	ON_COMMAND(ID_GEOM_NODE_MOVE, OnNodeMove)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_COMMAND(ID_ZOOM_IN, OnZoomIn)
	ON_COMMAND(ID_ZOOM_OUT, OnZoomOut)
	ON_UPDATE_COMMAND_UI(ID_ZOOM_IN, OnUpdateZoomIn)
	ON_UPDATE_COMMAND_UI(ID_ZOOM_OUT, OnUpdateZoomOut)
	ON_COMMAND(ID_NUM_NODE, OnNumNode)
	ON_UPDATE_COMMAND_UI(ID_NUM_NODE, OnUpdateNumNode)
	ON_COMMAND(ID_NUM_ELEM, OnNumElem)
	ON_UPDATE_COMMAND_UI(ID_NUM_ELEM, OnUpdateNumElem)
	ON_COMMAND(ID_NUM_INTP, OnNumIntp)
	ON_UPDATE_COMMAND_UI(ID_NUM_INTP, OnUpdateNumIntp)
	ON_COMMAND(ID_GEOM_NODE_OPEN, OnGeomNodeOpen)
	ON_COMMAND(ID_GEOM_NODE_MOUSE, OnGeomNodeMouse)
	ON_COMMAND(ID_GEOM_ELEM_ALL, OnGeomElemAll)
	ON_COMMAND(ID_GEOM_ELEM_ADD, OnGeomElemAdd)
	ON_COMMAND(ID_GEOM_ELEM_DEL, OnGeomElemDel)
	ON_WM_RBUTTONDOWN()
	ON_COMMAND(ID_INTER_ADD, OnInterAdd)
	ON_COMMAND(ID_INTER_ADD_MOUSE, OnInterAddMouse)
	ON_COMMAND(ID_INTER_DEL, OnInterDel)
	ON_COMMAND(ID_INTER_MOVE, OnInterMove)
	ON_COMMAND(ID_INTER_OPEN, OnInterOpen)
	ON_UPDATE_COMMAND_UI(ID_INTER_MOVE, OnUpdateInterMove)
	ON_UPDATE_COMMAND_UI(ID_INTER_DEL, OnUpdateInterDel)
	ON_COMMAND(ID_BOUN_NEW, OnBounNew)
	ON_COMMAND(ID_BOUN_ALL, OnBounAll)
	ON_UPDATE_COMMAND_UI(ID_BOUN_ALL, OnUpdateBounAll)
	ON_COMMAND(ID_BOUN_EDIT, OnBounEdit)
	ON_COMMAND(ID_WELL_ADD, OnWellAdd)
	ON_COMMAND(ID_WELL_ADD_MOUSE, OnWellAddMouse)
	ON_COMMAND(ID_WELL_DELETE, OnWellDelete)
	ON_COMMAND(ID_WELL_EDIT, OnWellEdit)
	ON_COMMAND(ID_WELL_MOVE, OnWellMove)
	ON_COMMAND(ID_ZOOM_FULL, OnZoomFull)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CZoomView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CZoomView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CZoomView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBemInpView construction/destruction

CBemInpView::CBemInpView()
{
	IsNumNod=IsNumEl=IsNumInt=IsButDown=FALSE;
	LBut=0;prnum=-1;
}

CBemInpView::~CBemInpView()
{
}

BOOL CBemInpView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CZoomView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CBemInpView drawing

void CBemInpView::OnDraw(CDC* pDC)
{
	CBemInpDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	pDoc->PlotNod (pDC,3,IsNumNod);
	pDoc->PlotElem (pDC,IsNumEl);
	pDoc->PlotIntPt (pDC,3,IsNumInt);
	pDoc->PlotWells (pDC,3);
}

void CBemInpView::OnInitialUpdate()
{
	CZoomView::OnInitialUpdate();
	CBemInpDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	CRect rc;
	GetClientRect (&rc);
	pDoc->ScaleNods(rc);
	SetZoomSizes(pDoc->GetDocSize());
}

/////////////////////////////////////////////////////////////////////////////
// CBemInpView printing

BOOL CBemInpView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CBemInpView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CBemInpView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CBemInpView diagnostics

#ifdef _DEBUG
void CBemInpView::AssertValid() const
{
	CZoomView::AssertValid();
}

void CBemInpView::Dump(CDumpContext& dc) const
{
	CZoomView::Dump(dc);
}

CBemInpDoc* CBemInpView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CBemInpDoc)));
	return (CBemInpDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CBemInpView message handlers

void CBemInpView::OnNodeAdd() 
{
	CBemInpDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	pDoc->NewNods();
	CRect rc;
	GetClientRect (&rc);
	pDoc->ScaleNods(rc);
	Invalidate();
}

void CBemInpView::OnNodeDelete() 
{
	LBut=ND_DEL;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnNodeMove() 
{
	LBut=ND_MOVE;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	int i,in;
	CString msg;
	CZoomView::OnLButtonDown(nFlags, point);
	CBemInpDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	ViewDPtoLP (&point,1);
	switch (LBut)
	{
	case ND_DEL:
		in=pDoc->FindNode(point);
		if (in<0)
		{
			AfxMessageBox ("Node is not found!");
		}
		else
		{
			msg.Format ("Are you sure to delete node no.%d?",in+1);
			i=AfxMessageBox(msg,MB_YESNO);
			if (i==IDYES)
			{
				pDoc->DelNode(in);
				pDoc->SetModifiedFlag();
				Invalidate();
			}
		}
		break;
	case ND_MOVE:
		in=pDoc->FindNode(point);
		if (in<0)
		{
			AfxMessageBox ("Node is not found!");
		}
		else
		{
			prnum=in;IsButDown=TRUE;
			pDoc->SetModifiedFlag();
		}
		break;
	case ND_ADD:
		pDoc->AddNode(point);
		Invalidate();
		break;
	case IN_DEL:
		in=pDoc->FindIntPt(point);
		if (in<0)
		{
			AfxMessageBox ("Point is not found!");
		}
		else
		{
			msg.Format ("Are you sure to delete point no.%d?",in+1);
			i=AfxMessageBox(msg,MB_YESNO);
			if (i==IDYES)
			{
				pDoc->DelIntPt(in);
				pDoc->SetModifiedFlag();
				Invalidate();
			}
		}
		break;
	case IN_MOVE:
		in=pDoc->FindIntPt(point);
		if (in<0)
		{
			AfxMessageBox ("Point is not found!");
		}
		else
		{
			prnum=in;IsButDown=TRUE;
			pDoc->SetModifiedFlag();
		}
		break;
	case IN_ADD:
		pDoc->AddIntPt(point);
		Invalidate();
		break;
	case WL_DEL:
		in=pDoc->FindWell(point);
		if (in<0)
		{
			AfxMessageBox ("Well is not found!");
		}
		else
		{
			msg="Are you sure to delete well ";
			CWell* wl=pDoc->GetWell(in);
			msg+=wl->name+"?";
			i=AfxMessageBox(msg,MB_YESNO);
			if (i==IDYES)
			{
				pDoc->DelWell(in);
				pDoc->SetModifiedFlag();
				Invalidate();
			}
		}
		break;
	case WL_MOVE:
		in=pDoc->FindWell(point);
		if (in<0)
		{
			AfxMessageBox ("Well is not found!");
		}
		else
		{
			prnum=in;IsButDown=TRUE;
			pDoc->SetModifiedFlag();
		}
		break;
	case WL_ADD:
		msg.Format("W-%d",pDoc->Wells.GetSize()+1);
		pDoc->AddWell(msg,point,0.0f,0.1f);
		Invalidate();
		break;
	case WL_EDIT:
		in=pDoc->FindWell(point);
		if (in<0)
		{
			AfxMessageBox ("Well is not found!");
		}
		else
		{
			CWell* wl=pDoc->GetWell(in);
			CAddWell aw;
			aw.m_name=wl->name;aw.m_x=wl->xz;aw.m_y=wl->yz;
			aw.m_q=wl->yield;aw.m_diam=wl->diam;
			if (aw.DoModal()==IDOK)
			{
				wl->name=aw.m_name;wl->xz=aw.m_x;wl->yz=aw.m_y;
				wl->yield=aw.m_q;wl->diam=aw.m_diam;
				pDoc->SetModifiedFlag();
			}
			Invalidate();			
		}
		break;
	case EL_ADD:
		if (prnum<0)
		{
			in=pDoc->FindNode(point);
			if (in<0)
				AfxMessageBox ("Node is not found!");
			else
				prnum=in;
		}
		else
		{
			in=pDoc->FindNode(point);
			if (in<0)
				AfxMessageBox ("Node is not found!");
			else
			{
				pDoc->AddElement(prnum,in);
				prnum=-1;
				Invalidate();
			}
		}
		break;
	case EL_ALL:
		if (prnum<0)
		{
			in=pDoc->FindNode(point);
			if (in<0)
				AfxMessageBox ("Node is not found!");
			else
				prnum=in;
		}
		else
		{
			in=pDoc->FindNode(point);
			if (in<0)
				AfxMessageBox ("Node is not found!");
			else
			{
				pDoc->AddElement(prnum,in);
				prnum=in;
				Invalidate();
			}
		}
		break;
	case EL_DEL:
		in=pDoc->FindElem(point);
		if (in<0)
			AfxMessageBox ("Element is not found!");
		else
		{
			msg.Format("Do you really want to delete element no.%d?",in+1);
			i=AfxMessageBox (msg,MB_YESNO);
			if (i==IDYES)
			{
				pDoc->DelElem(in);
				Invalidate();
			}
		}				
		break;
	case BO_NEW:
		in=pDoc->FindElem(point);
		if (in<0)
			AfxMessageBox ("Element is not found!");
		else
		{
			CElement* el=pDoc->GetElement(in);
			el->type=type;
			switch (type)
			{
			case 1:
				el->pot=poten;
				break;
			case 2:
				el->der=deriv;
				break;
			case 3:
				el->level=poten;
				el->kf0=coef;el->dist=dist;
				break;
			}
			pDoc->SetModifiedFlag();
			Invalidate();
		}
		break;
	case BO_EDIT:
		in=pDoc->FindElem(point);
		if (in<0)
			AfxMessageBox ("Element is not found!");
		else
		{
			CElement* el=pDoc->GetElement(in);
			CBounDial boun;
			boun.m_head.Format("Boundary condition at %d.el.",in+1);
			boun.m_kind=el->type-1;
			boun.m_poten=el->pot;
			if (el->type==3) boun.m_poten=el->level;
			boun.m_deriv=el->der;boun.m_coef=el->kf0;
			boun.m_dist=el->dist;
			if (boun.DoModal()==IDOK)
			{
				type=boun.m_kind+1;
				poten=boun.m_poten;deriv=boun.m_deriv;
				coef=boun.m_coef;dist=boun.m_dist;
				el->type=type;
				switch (type)
				{
				case 1:
					el->pot=poten;
					break;
				case 2:
					el->der=deriv;
					break;
				case 3:
					el->level=poten;
					el->kf0=coef;el->dist=dist;
					break;
				}
				pDoc->SetModifiedFlag();
			}
			Invalidate();
		}
		break;
	}
}

void CBemInpView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	CZoomView::OnLButtonUp(nFlags, point);
	switch (LBut)
	{
	case ND_MOVE:case WL_MOVE:case IN_MOVE:
		IsButDown=FALSE;
		break;
	}
}

void CBemInpView::OnMouseMove(UINT nFlags, CPoint point) 
{
	CZoomView::OnMouseMove(nFlags, point);
	CBemInpDoc* pDoc = GetDocument();
	CMainFrame* pMain=(CMainFrame*)AfxGetMainWnd();
	float xb,yb;
	CString msg;
	ASSERT_VALID(pDoc);
	ViewDPtoLP (&point,1);
	switch (LBut)
	{
	case ND_ADD:case WL_ADD:
		RevTran (pDoc->gcb,point,xb,yb);
		msg.Format("x=%.3f, y=%.3f",xb,yb);
		pMain->m_wndStatusBar.SetPaneText(0,msg);
		break;
	case ND_MOVE:
		if (IsButDown && prnum>=0)
		{
			CNode* nd=pDoc->GetNode(prnum);
			nd->xi=point.x;nd->yi=point.y;
			nd->RevTran(pDoc->gcb);
			msg.Format("x=%.3f, y=%.3f",nd->xb,nd->yb);
			pMain->m_wndStatusBar.SetPaneText(0,msg);
			Invalidate();
		}
		break;
	case IN_MOVE:
		if (IsButDown && prnum>=0)
		{
			CIntPoint* nd=pDoc->GetIntPt(prnum);
			nd->xi=point.x;nd->yi=point.y;
			nd->RevTran(pDoc->gcb);
			msg.Format("x=%.3f, y=%.3f",nd->xz,nd->yz);
			pMain->m_wndStatusBar.SetPaneText(0,msg);
			Invalidate();
		}
		break;
	case WL_MOVE:
		if (IsButDown && prnum>=0)
		{
			CWell* nd=pDoc->GetWell(prnum);
			nd->xi=point.x;nd->yi=point.y;
			nd->RevTran(pDoc->gcb);
			msg.Format("x=%.3f, y=%.3f",nd->xz,nd->yz);
			pMain->m_wndStatusBar.SetPaneText(0,msg);
			Invalidate();
		}
		break;
	}
}

void CBemInpView::OnZoomIn() 
{
	// Toggle zoomin mode
	LBut=0;
	CWnd *pWin = ((CWinApp *) AfxGetApp())->m_pMainWnd;
	if (GetZoomMode() == MODE_ZOOMIN) {
		SetZoomMode(MODE_ZOOMOFF);
		// Clear the statusbar
		pWin->SendMessage(WM_SETMESSAGESTRING, 0, 
			(LPARAM)(LPCSTR)"");
	} else {
		SetZoomMode(MODE_ZOOMIN);
		// Give instructions in the statusbar
		pWin->SendMessage(WM_SETMESSAGESTRING, 0, 
			(LPARAM)(LPCSTR)"Click to zoom in on point or drag a zoom box.");
	}
}

void CBemInpView::OnZoomOut() 
{
	// Toggle zoomout mode
	LBut=0;
	CWnd *pWin = ((CWinApp *) AfxGetApp())->m_pMainWnd;
	if (GetZoomMode() == MODE_ZOOMOUT) {
		SetZoomMode(MODE_ZOOMOFF);
		// Clear the statusbar
		pWin->SendMessage(WM_SETMESSAGESTRING, 0, 
			(LPARAM)(LPCSTR)"");
	} else {
		SetZoomMode(MODE_ZOOMOUT);
		// Give instructions in the statusbar
		pWin->SendMessage(WM_SETMESSAGESTRING, 0, 
			(LPARAM)(LPCSTR)"Click to zoom out on point.");
	}
}

void CBemInpView::OnUpdateZoomIn(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(GetZoomMode() == MODE_ZOOMIN);
}

void CBemInpView::OnUpdateZoomOut(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(GetZoomMode() == MODE_ZOOMOUT);
}

void CBemInpView::OnNumNode() 
{
	if (IsNumNod) IsNumNod=FALSE;
	else IsNumNod=TRUE;
	Invalidate();
}

void CBemInpView::OnUpdateNumNode(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(IsNumNod);
}

void CBemInpView::OnNumElem() 
{
	if (IsNumEl) IsNumEl=FALSE;
	else IsNumEl=TRUE;
	Invalidate();
}

void CBemInpView::OnUpdateNumElem(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(IsNumEl);
}

void CBemInpView::OnNumIntp() 
{
	if (IsNumInt) IsNumInt=FALSE;
	else IsNumInt=TRUE;
	Invalidate();
}

void CBemInpView::OnUpdateNumIntp(CCmdUI* pCmdUI) 
{
	pCmdUI->SetCheck(IsNumInt);
}

void CBemInpView::OnGeomNodeOpen() 
{
	CBemInpDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	pDoc->OpenNods();
	CRect rc;
	GetClientRect (&rc);
	pDoc->ScaleNods(rc);
	Invalidate();
}

void CBemInpView::OnGeomNodeMouse() 
{
	LBut=ND_ADD;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnGeomElemAll() 
{
	LBut=EL_ALL;prnum=-1;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnGeomElemAdd() 
{
	LBut=EL_ADD;prnum=-1;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnGeomElemDel() 
{
	LBut=EL_DEL;
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	LBut=0;	
	CZoomView::OnRButtonDown(nFlags, point);
}

void CBemInpView::OnInterAdd() 
{
	CBemInpDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	pDoc->NewPoint();
	Invalidate();
}

void CBemInpView::OnInterAddMouse() 
{
	LBut=IN_ADD;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnInterDel() 
{
	LBut=IN_DEL;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnInterMove() 
{
	LBut=IN_MOVE;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnInterOpen() 
{
	CBemInpDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	pDoc->OpenPoints();
	Invalidate();
}

void CBemInpView::OnUpdateInterMove(CCmdUI* pCmdUI) 
{
	if (LBut==IN_MOVE) pCmdUI->SetCheck(1);
	else pCmdUI->SetCheck(0);
}

void CBemInpView::OnUpdateInterDel(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	
}

void CBemInpView::OnBounNew() 
{
	CBounDial boun;
	boun.m_head="New boundary condition";
	boun.m_kind=0;
	if (boun.DoModal()==IDOK)
	{
		type=boun.m_kind+1;
		poten=boun.m_poten;deriv=boun.m_deriv;
		coef=boun.m_coef;dist=boun.m_dist;
		LBut=BO_NEW;
	}
}

void CBemInpView::OnBounAll() 
{
	int i;
	CBemInpDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	CBounDial boun;
	boun.m_head="New boundary condition";
	boun.m_kind=0;
	if (boun.DoModal()==IDOK)
	{
		type=boun.m_kind+1;
		poten=boun.m_poten;deriv=boun.m_deriv;
		coef=boun.m_coef;dist=boun.m_dist;
		for (i=0;i<pDoc->Elems.GetSize();i++)
		{
			CElement* el=pDoc->GetElement(i);
			el->type=type;
			switch (type)
			{
			case 1:
				el->pot=poten;
				break;
			case 2:
				el->der=deriv;
				break;
			case 3:
				el->level=poten;
				el->kf0=coef;el->dist=dist;
				break;
			}
		}
		Invalidate();
	}
}

void CBemInpView::OnUpdateBounAll(CCmdUI* pCmdUI) 
{
	
}

void CBemInpView::OnBounEdit() 
{
	LBut=BO_EDIT;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnWellAdd() 
{
	CAddWell aw;
	CBemInpDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (aw.DoModal()==IDOK)
	{
		pDoc->AddWell(aw.m_name,aw.m_x,aw.m_y,aw.m_q,aw.m_diam);
		Invalidate();
	}
}

void CBemInpView::OnWellAddMouse() 
{
	LBut=WL_ADD;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnWellDelete() 
{
	LBut=WL_DEL;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnWellEdit() 
{
	LBut=WL_EDIT;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::OnWellMove() 
{
	LBut=WL_MOVE;	
	SetZoomMode(MODE_ZOOMOFF);
}

void CBemInpView::RevTran(float *gcb, CPoint p, float &xb, float &yb)
{
 	xb=((float)p.x-gcb[0])/gcb[1]+gcb[2];
 	yb=((float)p.y-gcb[3])/gcb[4]+gcb[5];
}

void CBemInpView::OnZoomFull() 
{
	DoZoomFull();	
}
