// CNCDlg.cpp : 実装ファイル
//

#include "stdafx.h"
#include "CNC.h"
#include "CNCDlg.h"

#include "CAO_i.c"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CCNCDlg ダイアログ
CCNCDlg::CCNCDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CCNCDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	m_eng   = NULL;
	m_wss   = NULL;
	m_ws    = NULL;
	m_ctrl  = NULL;
	m_CNC = NULL;
	m_tsk   = NULL;
	//m_varCurAng = NULL;
	m_varCurPos = NULL;
	m_varDummy  = NULL;
}

void CCNCDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_BUTTON_INIT, btnInit);
	DDX_Control(pDX, IDC_BUTTON_CONNECT, btnConnect);
	DDX_Control(pDX, IDC_BUTTON_DISCONNECT, btnDisconnect);
	DDX_Control(pDX, IDC_LABEL_DISP, lblDsp);
	//DDX_Control(pDX, IDC_BUTTON_READ_CURANG, btnReadCurAng);
	DDX_Control(pDX, IDC_BUTTON_READ_CURPOS, btnReadCurPos);
	DDX_Control(pDX, IDC_BUTTON_READ_DUMMY, btnReadDummy);
	DDX_Control(pDX, IDC_BUTTON_START, btnStart);
	DDX_Control(pDX, IDC_BUTTON_STOP, btnStop);
}

BEGIN_MESSAGE_MAP(CCNCDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_BUTTON_INIT, &CCNCDlg::OnBnClickedButtonInit)
	ON_BN_CLICKED(IDC_BUTTON_CONNECT, &CCNCDlg::OnBnClickedButtonConnect)
	ON_BN_CLICKED(IDC_BUTTON_DISCONNECT, &CCNCDlg::OnBnClickedButtonDisconnect)
	//ON_BN_CLICKED(IDC_BUTTON_READ_CURANG, &CCNCDlg::OnBnClickedButtonReadCurang)
	ON_BN_CLICKED(IDC_BUTTON_READ_CURPOS, &CCNCDlg::OnBnClickedButtonReadCurpos)
	ON_BN_CLICKED(IDC_BUTTON_READ_DUMMY, &CCNCDlg::OnBnClickedButtonReadDummy)
	ON_BN_CLICKED(IDC_BUTTON_START, &CCNCDlg::OnBnClickedButtonStart)
	ON_BN_CLICKED(IDC_BUTTON_STOP, &CCNCDlg::OnBnClickedButtonStop)
END_MESSAGE_MAP()


// CCNCDlg メッセージ ハンドラ

BOOL CCNCDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、
	//  Framework は、この設定を自動的に行います。
	SetIcon(m_hIcon, TRUE);			// 大きいアイコンの設定
	SetIcon(m_hIcon, FALSE);		// 小さいアイコンの設定

	CoInitialize(NULL);

	return TRUE;  // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
}

void CCNCDlg::OnDestroy()
{
	CDialog::OnDestroy();

	OnBnClickedButtonDisconnect();

	if(m_ws)
	{
		m_ws->Release();
		m_ws = NULL;
	}

	if(m_wss)
	{
		m_wss->Release();
		m_wss = NULL;
	}

	if(m_eng)
	{
		m_eng->Release();
		m_eng = NULL;
	}

	CoUninitialize();
}

// ダイアログに最小化ボタンを追加する場合、アイコンを描画するための
//  下のコードが必要です。ドキュメント/ビュー モデルを使う MFC アプリケーションの場合、
//  これは、Framework によって自動的に設定されます。

void CCNCDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 描画のデバイス コンテキスト

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// クライアントの四角形領域内の中央
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// アイコンの描画
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// ユーザーが最小化したウィンドウをドラッグしているときに表示するカーソルを取得するために、
//  システムがこの関数を呼び出します。
HCURSOR CCNCDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CCNCDlg::OnBnClickedButtonInit()
{
	// Create CAO Engine
	CoCreateInstance(CLSID_CaoEngine, NULL, CLSCTX_LOCAL_SERVER, IID_ICaoEngine, (void**)&m_eng);
	m_eng->get_Workspaces(&m_wss);
	m_wss->Item(CComVariant(0L), &m_ws);

	btnInit.EnableWindow(FALSE);
	btnConnect.EnableWindow(TRUE);
}

void CCNCDlg::OnBnClickedButtonConnect()
{
	HRESULT hr = E_FAIL;

	// Connect Dummy.CNC Provider
	if(m_ws != NULL)
	{
		hr = m_ws->AddController(CComBSTR(L"CNC"), CComBSTR(L"CaoProv.Dummy.CNC"), CComBSTR(L""), CComBSTR(L""), &m_ctrl);
		
		if(SUCCEEDED(hr))
		{
			m_ctrl->AddRobot(CComBSTR(L"CNC"), CComBSTR(L""), &m_CNC);
			m_ctrl->AddTask(CComBSTR(L"Prg1"), CComBSTR(L""), &m_tsk);
			//m_CNC->AddVariable(CComBSTR(L"@CURRENT_ANGLE"), CComBSTR(L""), &m_varCurAng);
			m_CNC->AddVariable(CComBSTR(L"@CURRENT_POSITION"), CComBSTR(L""), &m_varCurPos);
			m_CNC->AddVariable(CComBSTR(L"@DUMMY"), CComBSTR(L""), &m_varDummy);
		}
	}

	if(SUCCEEDED(hr))
	{
		// Enable command buttons
		btnConnect.EnableWindow(FALSE);
		btnDisconnect.EnableWindow(TRUE);
		//btnReadCurAng.EnableWindow(TRUE);
		btnReadCurPos.EnableWindow(TRUE);
		btnReadDummy.EnableWindow(TRUE);
		btnStart.EnableWindow(TRUE);
		btnStop.EnableWindow(TRUE);
	}
	else
	{
		OnBnClickedButtonDisconnect();
		ShowErrorMessage(hr);
	}
}

void CCNCDlg::OnBnClickedButtonDisconnect()
{
	if(m_varDummy){
		m_varDummy->Release();
		m_varDummy = NULL;
	}

	if(m_varCurPos){
		m_varCurPos->Release();
		m_varCurPos = NULL;
	}

	/*if(m_varCurAng){
		m_varCurAng->Release();
		m_varCurAng = NULL;
	}*/

	if(m_tsk != NULL) {
		m_tsk->Release();
		m_tsk = NULL;
	}

	if(m_CNC){
		m_CNC->Release();
		m_CNC=NULL;
	}

	// Disconnect Provider
	if(m_ctrl)
	{
		if(m_ws)
		{
			CComVariant vntCtrlName;
			CComPtr<ICaoControllers> ctrls;

			m_ws->get_Controllers(&ctrls);

			vntCtrlName.vt = VT_BSTR;
			m_ctrl->get_Name(&vntCtrlName.bstrVal);

			ctrls->Remove(vntCtrlName);
		}

		m_ctrl->Release();
		m_ctrl = NULL;
	}

	// Disable command buttons
	btnConnect.EnableWindow(TRUE);
	btnDisconnect.EnableWindow(FALSE);
	//btnReadCurAng.EnableWindow(FALSE);
	btnReadCurPos.EnableWindow(FALSE);
	btnReadDummy.EnableWindow(FALSE);
	btnStart.EnableWindow(FALSE);
	btnStop.EnableWindow(FALSE);
}

/*void CCNCDlg::OnBnClickedButtonReadCurang()
{
	HRESULT hr;
	CString strValue;
	CComVariant vntValue;
	double* dData;

	hr = m_varCurAng->get_Value(&vntValue);

	if(SUCCEEDED(hr))
	{
		SafeArrayAccessData(vntValue.parray, (void**)&dData);
		strValue.Format(_T("%.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f"),
			dData[0], dData[1], dData[2], dData[3], dData[4], dData[5], dData[6], dData[7]);
		SafeArrayUnaccessData(vntValue.parray);

		lblDsp.SetWindowText(strValue);
	}
	else
	{
		ShowErrorMessage(hr);
	}
}*/

void CCNCDlg::OnBnClickedButtonReadCurpos()
{
	HRESULT hr;
	CString strValue;
	CComVariant vntValue;
	double* dData;

	hr = m_varCurPos->get_Value(&vntValue);

	if(SUCCEEDED(hr))
	{
		SafeArrayAccessData(vntValue.parray, (void**)&dData);
		strValue.Format(_T("%.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %d"),
			dData[0], dData[1], dData[2], dData[3], dData[4], dData[5], (int)dData[6]);
		SafeArrayUnaccessData(vntValue.parray);

		lblDsp.SetWindowText(strValue);
	}
	else
	{
		ShowErrorMessage(hr);
	}
}

void CCNCDlg::OnBnClickedButtonReadDummy()
{
	HRESULT hr;
	CString strValue;
	CComVariant vntValue;
	double* dData;

	hr = m_varDummy->get_Value(&vntValue);

	if(SUCCEEDED(hr))
	{
		SafeArrayAccessData(vntValue.parray, (void**)&dData);
		strValue.Format(_T("%.1f, %.1f, %.1f"),
			dData[0], dData[1], dData[2]);
		SafeArrayUnaccessData(vntValue.parray);

		lblDsp.SetWindowText(strValue);
	}
	else
	{
		ShowErrorMessage(hr);
	}
}

void CCNCDlg::OnBnClickedButtonStart()
{
	// Start [1:One cycle execution, 2:Continuous execution, 3:Step forward]
	HRESULT hr = m_tsk->Start(2, CComBSTR(L""));
	if(FAILED(hr)) {
		ShowErrorMessage(hr);
	}
}

void CCNCDlg::OnBnClickedButtonStop()
{
	// Stop [0:Default stop, 1:Instant stop, 2:Step stop, 3:Cycle stop, 4:Initialized stop]
	HRESULT hr = m_tsk->Stop(4, CComBSTR(L""));
	if(FAILED(hr)) {
		ShowErrorMessage(hr);
	}
}

void CCNCDlg::ShowErrorMessage(HRESULT hr)
{
	CString strMsg;
	strMsg.Format(_T("%X"), hr);
	MessageBox(strMsg, _T("Error"));
}