// VariableDlg.cpp : インプリメンテーション ファイル
//

#include "stdafx.h"
#include "Variable.h"
#include "VariableDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#include "CAO_i.c"

/////////////////////////////////////////////////////////////////////////////
// CVariableDlg ダイアログ

CVariableDlg::CVariableDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CVariableDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CVariableDlg)
		// メモ: この位置に ClassWizard によってメンバの初期化が追加されます。
	//}}AFX_DATA_INIT
	// メモ: LoadIcon は Win32 の DestroyIcon のサブシーケンスを要求しません。
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CVariableDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CVariableDlg)
		// メモ: この場所には ClassWizard によって DDX と DDV の呼び出しが追加されます。
		DDX_Control(pDX, IDC_COMBO_PARAMETER, m_cmbParam);
		DDX_Control(pDX, IDC_COMBO_VARIABLE, m_cmbType);
		DDX_Text(pDX, IDC_INDEX, m_editIndex);
		DDX_Text(pDX, IDC_VALUE, m_strValue);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CVariableDlg, CDialog)
	//{{AFX_MSG_MAP(CVariableDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_CONNECT, OnConnect)
	ON_BN_CLICKED(IDC_DISCONNECT, OnDisconnect)
	ON_BN_CLICKED(IDC_GET, OnGet)
	ON_BN_CLICKED(IDC_PUT, OnPut)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CVariableDlg メッセージ ハンドラ

BOOL CVariableDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// このダイアログ用のアイコンを設定します。フレームワークはアプリケーションのメイン
	// ウィンドウがダイアログでない時は自動的に設定しません。
	SetIcon(m_hIcon, TRUE);			// 大きいアイコンを設定
	SetIcon(m_hIcon, FALSE);		// 小さいアイコンを設定
	
	// TODO: 特別な初期化を行う時はこの場所に追加してください。
	HRESULT	hr = S_OK;
	CoInitialize(0);
	
	// Create CaoEngine object
	hr = CoCreateInstance(CLSID_CaoEngine, NULL, CLSCTX_LOCAL_SERVER, IID_ICaoEngine, (void**)&m_pIEng);
	if (FAILED(hr)) {
		return FALSE;
	}

	// Get Workespaces object
	hr = m_pIEng->get_Workspaces(&m_pIWss);
	if (FAILED(hr)) {
		return FALSE;
	}

	// Get Workspaces(0)
	hr = m_pIWss->Item(CComVariant(0L), &m_pIWs);
	if (FAILED(hr)) {
		return FALSE;
	}

	// Create CaoControllers object
	hr = m_pIWs->get_Controllers(&m_pICtrls);
	if (FAILED(hr)) {
		return FALSE;
	}

	m_cmbParam.SetCurSel(0);
	m_cmbType.SetCurSel(5);
	m_editIndex = "10";
	m_strValue  = "0,1,2,3,4,5";
	UpdateData(FALSE);

	((CButton *)GetDlgItem(IDC_GET))->EnableWindow(FALSE);
	((CButton *)GetDlgItem(IDC_PUT))->EnableWindow(FALSE);

	return TRUE;  // TRUE を返すとコントロールに設定したフォーカスは失われません。
}

void CVariableDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: この位置にメッセージ ハンドラ用のコードを追加してください
	OnDisconnect();

	m_pICtrls.Release();
	m_pIWs.Release();
	m_pIWss.Release();
	m_pIEng.Release();
}

// もしダイアログボックスに最小化ボタンを追加するならば、アイコンを描画する
// コードを以下に記述する必要があります。MFC アプリケーションは document/view
// モデルを使っているので、この処理はフレームワークにより自動的に処理されます。

void CVariableDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 描画用のデバイス コンテキスト

		SendMessage(WM_ICONERASEBKGND, (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();
	}
}

BOOL CVariableDlg::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください
	if(pMsg->message == WM_KEYDOWN){
		switch(pMsg->wParam){
			case VK_ESCAPE:	// Escキー押下
				return TRUE;

			default:
				break;
		}
	}

	return CDialog::PreTranslateMessage(pMsg);
}

// システムは、ユーザーが最小化ウィンドウをドラッグしている間、
// カーソルを表示するためにここを呼び出します。
HCURSOR CVariableDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CVariableDlg::OnConnect() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CString					strParam;
	CComPtr<ICaoController>	pICtrl;
	CComBSTR				bstrParam;
	HRESULT					hr;

	OnDisconnect();

	// パラメータを取得
	UpdateData();
	if(m_cmbParam.GetCurSel() < 0)
		m_cmbParam.GetWindowText(strParam);
	else
		m_cmbParam.GetLBText(m_cmbParam.GetCurSel(), strParam);

	// コントローラオブジェクトを追加
	bstrParam = CComBSTR("Conn=" + strParam);
	hr = m_pICtrls->Add(CComBSTR(L"Sample"), CComBSTR(L"CaoProv.DENSO.NetwoRC"), CComBSTR(L""), bstrParam, &pICtrl);
	if(FAILED(hr)) {
		AfxTrace("Error : AddController( %X )\n", hr);
		return;
	}

	((CButton *)GetDlgItem(IDC_GET))->EnableWindow(TRUE);
	((CButton *)GetDlgItem(IDC_PUT))->EnableWindow(TRUE);
}

void CVariableDlg::OnDisconnect() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	long	longValue;
	HRESULT	hr;

	hr = m_pICtrls->get_Count(&longValue);
	if(FAILED(hr)){
		AfxTrace("Error : get_Count( %X )\n", hr);
		return;
	}

	if(longValue > 0)
		m_pICtrls->Clear();

	((CButton *)GetDlgItem(IDC_GET))->EnableWindow(FALSE);
	((CButton *)GetDlgItem(IDC_PUT))->EnableWindow(FALSE);
}

void CVariableDlg::OnGet() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CComPtr<ICaoController>	pICtrl;
	CComPtr<ICaoVariable>	pIVar;
	CComVariant				varValue;
	HRESULT					hr;

	CString					strType;

	UpdateData();

	if(m_cmbType.GetCurSel() < 0)
		m_cmbType.GetWindowText(strType);
	else
		m_cmbType.GetLBText(m_cmbType.GetCurSel(), strType);

	strType += m_editIndex;

	pICtrl = GetControllerObject();
	if(pICtrl){
		hr = pICtrl->AddVariable(CComBSTR(static_cast<LPCTSTR>(strType)), CComBSTR(L""), &pIVar);
		if(FAILED(hr)){
			AfxTrace("Error : get_Value( %X )\n", hr);
			return;
		}

		hr = pIVar->get_Value(&varValue);
		if(FAILED(hr)){
			AfxTrace("Error : get_Value( %X )\n", hr);
			return;
		}

		m_strValue = GetResultVariant(varValue);
		UpdateData(FALSE);

		ReleaseVariableObject(pIVar);
	}
}

void CVariableDlg::OnPut() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CString					strType;

	CComPtr<ICaoController>	pICtrl;
	CComPtr<ICaoVariable>	pIVar;

	CComVariant				varValue;
	HRESULT					hr;

	UpdateData();

	if(m_cmbType.GetCurSel() < 0)
		m_cmbType.GetWindowText(strType);
	else
		m_cmbType.GetLBText(m_cmbType.GetCurSel(), strType);

	strType += m_editIndex;

	pICtrl = GetControllerObject();
	if(pICtrl){
		hr = pICtrl->AddVariable(CComBSTR(static_cast<LPCTSTR>(strType)), CComBSTR(L""), &pIVar);
		if(FAILED(hr)){
			AfxTrace("Error : get_Value( %X )\n", hr);
			return;
		}

		UpdateData();

		switch(m_cmbType.GetCurSel()){
		case 0:		// I
			varValue = CComVariant(atoi(m_strValue));
			break;

		case 1:		// F
			varValue = CComVariant((float)atof(m_strValue));
			break;

		case 2:		// D
			varValue = CComVariant((double)atof(m_strValue));
			break;

		case 3:		// V
		case 4:		// P
		case 5:		// J
		case 6:		// T
		case 9:		// TOOL
		case 10:	// WORK
		case 11:	// AREA
			GetValueData(m_strValue, &varValue);
			break;

		case 7:		// S
			varValue = CComVariant(CComBSTR(static_cast<LPCTSTR>(m_strValue)));
			break;

		case 8:		// IO
			varValue = CComVariant((m_strValue.Compare("True") || m_strValue.Compare("TRUE") || m_strValue.Compare("true"))? bool(TRUE) : bool(FALSE));
			break;

		case 12:	// _ITP
		case 13:	// _PAC
		case 14:	// _DIO
		case 15:	// _ARM
		case 16:	// _SRV
		case 17:	// _SPD
		case 18:	// _VIS
		case 19:	// _COM
			varValue = CComVariant(atol(m_strValue));
			break;
		}

		hr = pIVar->put_Value(varValue);
		if(FAILED(hr)){
			AfxTrace("Error : put_Value( %d )\n", hr);
		}

		ReleaseVariableObject(pIVar);
	}
}

CComPtr<ICaoController> CVariableDlg::GetControllerObject()
{
	long					longValue;
	long					i;

	CComPtr<ICaoController>	pICtrl;
	CComVariant				varIndex;
	HRESULT					hr;

	// コントローラオブジェクト取得
	if(m_pICtrls){
		hr = m_pICtrls->get_Count(&longValue);
		if(SUCCEEDED(hr)){
			for(i = 0; i < longValue; i++){
				varIndex = CComVariant(i);
				hr = m_pICtrls->Item(varIndex, &pICtrl);
				if(SUCCEEDED(hr))
					break;
			}

			if(i < longValue)
				return pICtrl;
		}
	}
	return NULL;
}

BOOL CVariableDlg::ReleaseVariableObject(CComPtr<ICaoVariable> pIVar)
{
	long					longIndex;

	CComPtr<ICaoController>	pICtrl;
	CComPtr<ICaoVariables>	pIVars;
	HRESULT					hr;

	hr = pIVar->get_Index(&longIndex);
	if(SUCCEEDED(hr)){
		pICtrl = GetControllerObject();
		if(pICtrl){
			hr = pICtrl->get_Variables(&pIVars);
			if(SUCCEEDED(hr)){
				hr = pIVars->Remove(CComVariant(longIndex));
				if(FAILED(hr)){
					AfxTrace("Error : Remove( %X )\n", hr);
					return TRUE;
				}
			}
		}
	}

	return FALSE;
}

BOOL CVariableDlg::GetValueData(CString str, CComVariant* varData)
{
	CString			strData = "";
	CArray<float, float>	arrayData;

	SAFEARRAYBOUND	rgb[1];
	SAFEARRAY*		psa;
	HRESULT			hr;

	float*			fltData;
	int				i;

	for(i = 0; i < str.GetLength(); i++){
		switch(str[i]){
		case ',':
		case '\0':
			arrayData.Add((float)atof(strData));
			strData = "";
			break;

		case ' ':
			break;

		default:
			strData += str[i];
			break;
		}
	}

	if(strData.GetLength())
		arrayData.Add((float)atof(strData));

	rgb[0].cElements = arrayData.GetSize();
	rgb[0].lLbound   = 0;

	if(psa = SafeArrayCreate(VT_R4, 1, rgb)){
		hr = SafeArrayAccessData(psa, (void **)&fltData);
		if(SUCCEEDED(hr)){
			for(i = 0; i < arrayData.GetSize(); i++)
				fltData[i] = arrayData[i];

			varData->parray = psa;
			varData->vt     = VT_ARRAY | VT_R4;

			SafeArrayUnaccessData(psa);

			return TRUE;
		}
	}
	return FALSE;
}

CString CVariableDlg::GetResultVariant(CComVariant varResult)
{
	long		longlBound, longUBound;
	CString		strWork, strResult = "";
	CString		fmtType, fmtTypeEnd;

	SAFEARRAY*	psa;

	HRESULT		hr;

	if(varResult.vt & VT_ARRAY){
		psa = varResult.parray;
		SafeArrayGetLBound(psa, 1, &longlBound);
		SafeArrayGetUBound(psa, 1, &longUBound);

		hr = SafeArrayLock(psa);
		if(SUCCEEDED(hr)){
			for(long i = longlBound; i <= longUBound; i++){
				switch(varResult.vt & VT_TYPEMASK){
				case VT_I2:
				case VT_UI2:
					{
						short shortResult;
						SafeArrayGetElement(psa, &i, (void*)&shortResult);
						strWork.Format((i == longUBound)? "%d" : "%d,", shortResult);
					}
					break;

				case VT_I4:
				case VT_UI4:
				case VT_INT:
				case VT_UINT:
					{
						long longResult;
						SafeArrayGetElement(psa, &i, (void*)&longResult);
						strWork.Format((i == longUBound)? "%d" : "%d,", longResult);
					}
					break;

				case VT_R4:
					{
						float fltResult;
						SafeArrayGetElement(psa, &i, (void*)&fltResult);
						strWork.Format((i == longUBound)? "%f" : "%f,", fltResult);
					}
					break;

				case VT_R8:
					{
						double dblResult;
						SafeArrayGetElement(psa, &i, (void*)&dblResult);
						strWork.Format((i == longUBound)? "%f" : "%f,", dblResult);
					}
					break;

				case VT_BSTR:
					{
						BSTR bstrResult;
						SafeArrayGetElement(psa, &i, (void*)&bstrResult);
						strWork.Format((i == longUBound)? "%s" : "%s,", bstrResult);
					}
					break;

				case VT_I1:
				case VT_UI1:
				case VT_BOOL:
					{
						BYTE byteResult;
						SafeArrayGetElement(psa, &i, (void*)&byteResult);
						strWork.Format((i == longUBound)? "%s" : "%s,", byteResult);
					}
					break;

				default:
					AfxTrace("Variant Type : ( %d )", varResult.vt & VT_TYPEMASK);
					break;
				}

				strResult += strWork;
			}
			SafeArrayUnlock(psa);
		}

	} else {
		switch(varResult.vt & VT_TYPEMASK){
		case VT_I1:
		case VT_I2:
		case VT_I4:
			strResult.Format("%d", varResult.iVal);
			break;

		case VT_UI1:
		case VT_UI2:
		case VT_UI4:
			strResult.Format("%d", varResult.uiVal);
			break;

		case VT_I8:
			strResult.Format("%d", varResult.lVal);
			break;

		case VT_UI8:
			strResult.Format("%d", varResult.ulVal);
			break;

		case VT_INT:
			strResult.Format("%d", varResult.intVal);
			break;

		case VT_UINT:
			strResult.Format("%d", varResult.uintVal);
			break;

		case VT_R4:
			strResult.Format("%d", varResult.fltVal);
			break;

		case VT_R8:
			strResult.Format("%d", varResult.dblVal);
			break;

		case VT_BSTR:
			strResult = varResult.bstrVal;
			break;

		case VT_BOOL:
			strResult.Format((varResult.boolVal == TRUE)? "True" : "False");
			break;

		default:
			AfxTrace("Variant Type : ( %d )", varResult.vt & VT_TYPEMASK);
			break;
		}
	}

	return strResult;
}

