// FileDlg.cpp : インプリメンテーション ファイル
//

#include "stdafx.h"
#include "File.h"
#include "FileDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#include "CAO_i.c"

/////////////////////////////////////////////////////////////////////////////
// CFileDlg ダイアログ

CFileDlg::CFileDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CFileDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CFileDlg)
		// メモ: この位置に ClassWizard によってメンバの初期化が追加されます。
	//}}AFX_DATA_INIT
	// メモ: LoadIcon は Win32 の DestroyIcon のサブシーケンスを要求しません。
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CFileDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFileDlg)
		// メモ: この場所には ClassWizard によって DDX と DDV の呼び出しが追加されます。
		DDX_Control(pDX, IDC_CMB_PARAM, m_cmbParam);
		DDX_Control(pDX, IDC_GET, m_cmd_Get);
		DDX_Control(pDX, IDC_PUT, m_cmd_Put);
		DDX_Control(pDX, IDC_LIST_LOCALFILE, m_list_LocalFile);
		DDX_Control(pDX, IDC_LIST_REMOTEFILE, m_list_RemoteFile);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CFileDlg, CDialog)
	//{{AFX_MSG_MAP(CFileDlg)
	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)
	ON_BN_CLICKED(IDC_OPEN, OnOpen)
	ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFileDlg メッセージ ハンドラ

BOOL CFileDlg::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_cmd_Get.EnableWindow(FALSE);
	m_cmd_Put.EnableWindow(FALSE);
	UpdateData(FALSE);

	return TRUE;  // TRUE を返すとコントロールに設定したフォーカスは失われません。
}

void CFileDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: この位置にメッセージ ハンドラ用のコードを追加してください
	OnDisconnect();

	m_pICtrls.Release();
	m_pIWs.Release();
	m_pIWss.Release();
	m_pIEng.Release();
}

BOOL CFileDlg::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください
	if(pMsg->message == WM_KEYDOWN){
		switch(pMsg->wParam){
			case VK_ESCAPE:	// Escキー押下
				return TRUE;

			default:
				break;
		}
	}

	return CDialog::PreTranslateMessage(pMsg);
}

// もしダイアログボックスに最小化ボタンを追加するならば、アイコンを描画する
// コードを以下に記述する必要があります。MFC アプリケーションは document/view
// モデルを使っているので、この処理はフレームワークにより自動的に処理されます。

void CFileDlg::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();
	}
}

// システムは、ユーザーが最小化ウィンドウをドラッグしている間、
// カーソルを表示するためにここを呼び出します。
HCURSOR CFileDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CFileDlg::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;
	}

	m_cmd_Get.EnableWindow();
	m_cmd_Put.EnableWindow();
	UpdateData(FALSE);

	OnRefresh();
}

void CFileDlg::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();

	m_list_RemoteFile.ResetContent();
	m_list_LocalFile.ResetContent();

	m_cmd_Get.EnableWindow(FALSE);
	m_cmd_Put.EnableWindow(FALSE);
	UpdateData(FALSE);
}

void CFileDlg::OnGet() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CComPtr<ICaoController>	pICtrl;
	CComPtr<ICaoFiles>		pIFiles;
	CComPtr<ICaoFile>		pIFile;
	CComVariant				varValue;
	HRESULT					hr;

	long					longIndex;
	CString					strFileName, strData;
	CByteArray				arrayByteData;
	CFile					file;
	int						nIndex;

	UpdateData();

	nIndex = m_list_RemoteFile.GetCurSel();
	if(nIndex >= 0){
		m_list_RemoteFile.GetText(nIndex, strFileName);

		pICtrl = GetControllerObject();
		if(pICtrl){
			hr = pICtrl->AddFile(CComBSTR(strFileName), CComBSTR(""), &pIFile);
			if(FAILED(hr)){
				AfxTrace("Error : AddFile( %X )\n", hr);
				return;
			}

			hr = pIFile->get_Value(&varValue);
			if(FAILED(hr)){
				AfxTrace("Error : get_Value( %X )\n", hr);
				return;
			}

			if(varValue.vt == VT_BSTR){
				AfxBSTR2CString(&strData, varValue.bstrVal);
				if(file.Open(strFileName, CFile::modeCreate | CFile::modeWrite)){
					file.Write(strData, strData.GetLength());
					file.Close();
				}
			} else if(varValue.vt == (VT_ARRAY | VT_UI1)){
				if(GetVriantByteData(varValue, &arrayByteData)){
					if(file.Open(strFileName, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary)){
						file.Write(arrayByteData.GetData(), sizeof(BYTE) * arrayByteData.GetSize());
						file.Close();
					}
				}
			}

			hr = pIFile->get_Index(&longIndex);
			if(FAILED(hr)){
				AfxTrace("Error : get_Index( %X )\n", hr);
				return;
			}

			hr = pICtrl->get_Files(&pIFiles);
			if(FAILED(hr)){
				AfxTrace("Error : get_Files( %X )\n", hr);
				return;
			}

			hr = pIFiles->Remove(CComVariant(longIndex));
			if(FAILED(hr)){
				AfxTrace("Error : Remove( %X )\n", hr);
				return;
			}

			OnRefresh();
		}
	}
}

void CFileDlg::OnPut() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CComPtr<ICaoController>	pICtrl;
	CComPtr<ICaoFiles>		pIFiles;
	CComPtr<ICaoFile>		pIFile;
	CComVariant				varValue;
	HRESULT					hr;

	CString					strFileName, strExtension, strData;
	BYTE*					arrayByteData;
	CFile					file;
	long					longIndex;
	int						nIndex;

	UpdateData();
	
	nIndex = m_list_LocalFile.GetCurSel();
	if(nIndex >= 0){
		m_list_LocalFile.GetText(nIndex, strFileName);

		pICtrl = GetControllerObject();
		if(pICtrl){
			hr = pICtrl->AddFile(CComBSTR(strFileName), CComBSTR("@Create=1"), &pIFile);	// 1:Create new file
			if(FAILED(hr)){
				AfxTrace("Error : AddFile( %X )\n", hr);
				return;
			}

			strExtension = PathFindExtension(strFileName);
			if(strExtension.Compare(".nic") == 0){
				if(file.Open(strFileName, CFile::modeRead | CFile::typeBinary)){
					arrayByteData = new BYTE[file.GetLength()];
					file.Read(arrayByteData, file.GetLength());

					if(GetByteDataVariant(arrayByteData, file.GetLength(), &varValue)){
						hr = pIFile->put_Value(varValue);
						if(FAILED(hr)){
							AfxTrace("Error : put_Value( %X )\n", hr);
							return;
						}
					}

					file.Close();

					delete [] arrayByteData;
				}
			} else {
				if(file.Open(strFileName, CFile::modeRead)){
					file.Read(strData.GetBuffer(0), file.GetLength());
					file.Close();

					hr = pIFile->put_Value(CComVariant(strData));
					if(FAILED(hr)){
						AfxTrace("Error : put_Value( %X )\n", hr);
						return;
					}
				}
			}

			hr = pIFile->get_Index(&longIndex);
			if(FAILED(hr)){
				AfxTrace("Error : get_Index( %X )\n", hr);
				return;
			}

			hr = pICtrl->get_Files(&pIFiles);
			if(FAILED(hr)){
				AfxTrace("Error : get_Files( %X )\n", hr);
				return;
			}

			hr = pIFiles->Remove(CComVariant(longIndex));
			if(FAILED(hr)){
				AfxTrace("Error : Remove( %X )\n", hr);
				return;
			}

			OnRefresh();
		}
	}
}

void CFileDlg::OnOpen() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CString strFileName;
	int		nIndex;

	UpdateData();

	nIndex = m_list_LocalFile.GetCurSel();
	if(nIndex >= 0){
		m_list_LocalFile.GetText(nIndex, strFileName);

	
		ShellExecute(NULL, "open", "notepad.exe", strFileName, "", SW_SHOWNORMAL);
	}
}

void CFileDlg::OnRefresh() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	long					i, longValue;

	CComPtr<ICaoController>	pICtrl;
	CComPtr<ICaoFiles>		pIFiles;
	CComPtr<ICaoFile>		pIFile;
	CComVariant				varFileNames, varFileName;
	HRESULT					hr;

	CStringArray			arrayFileName;
	CFileFind				find;
	CString					strFileName, strExtension;


	pICtrl = GetControllerObject();
	if(pICtrl){
		UpdateData();

		// Remote File List
		hr = pICtrl->get_Files(&pIFiles);
		if(FAILED(hr)){
			AfxTrace("Error : get_Files( %X )\n", hr);
			return;
		}

		hr = pIFiles->get_Count(&longValue);
		if(FAILED(hr)){
			AfxTrace("Error : get_Count( %X )\n", hr);
			return;
		}
		for(i = 0; i < longValue; i++){
			hr = pIFiles->Remove(CComVariant(i));
			if(FAILED(hr)){
				AfxTrace("Error : Remove( %X )\n", hr);
			}
		}
	
		m_list_RemoteFile.ResetContent();

		// Append all file into ICaoController Files
		hr = pICtrl->get_FileNames(CComBSTR(L""), &varFileNames);
		if(FAILED(hr)){
			AfxTrace("Error : get_FileNames( %X )\n", hr);
		}

		if(GetVriantBSTRData(varFileNames, &arrayFileName)){
			for(i = 0; i < arrayFileName.GetSize(); i++){
				strExtension = PathFindExtension(arrayFileName.GetAt(i));
				if((strExtension.Compare(".pac") == 0) || (strExtension.Compare(".h") == 0) || (strExtension.Compare(".nic") == 0))
					m_list_RemoteFile.AddString(arrayFileName.GetAt(i));
			}
		}

		// Local File List
		m_list_LocalFile.ResetContent();

		BOOL bResult = find.FindFile();
		while(bResult){
			bResult = find.FindNextFile();

			if(find.IsDots())
				continue;

			strFileName = find.GetFileName();
			strExtension = PathFindExtension(strFileName);
			if((strExtension.Compare(".pac") == 0) || (strExtension.Compare(".h") == 0) || (strExtension.Compare(".nic") == 0))
				m_list_LocalFile.AddString(strFileName);
		}
	}

	UpdateData(FALSE);
}

CComPtr<ICaoController> CFileDlg::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 CFileDlg::GetVriantBSTRData(CComVariant varData, CStringArray* arrayData)
{
	long		longlBound, longUBound;
	CString		strData;

	CComVariant	varBSTRData;
	SAFEARRAY	*psa;
	HRESULT		hr;

	if(strData){
		if(varData.vt == (VT_ARRAY | VT_VARIANT)){
			psa = varData.parray;
			SafeArrayGetLBound(psa, 1, &longlBound);
			SafeArrayGetUBound(psa, 1, &longUBound);

			if(psa->cDims == 1){
				hr = SafeArrayLock(psa);
				if(SUCCEEDED(hr)){
					for(long i = longlBound; i <= longUBound; i++){
						SafeArrayGetElement(psa, &i, &varBSTRData);
						if(varBSTRData.vt == VT_BSTR){
							AfxBSTR2CString(&strData, varBSTRData.bstrVal);
							arrayData->Add(strData);
						}
					}
					SafeArrayUnlock(psa);
					return TRUE;
				}
			}
		}
	}
	return FALSE;
}

BOOL CFileDlg::GetVriantByteData(CComVariant varData, CByteArray* arrayData)
{
	long		longlBound, longUBound;
	CString		strData;

	BYTE		byteData;
	SAFEARRAY	*psa;
	HRESULT		hr;

	if(strData){
		if(varData.vt == (VT_ARRAY | VT_UI1)){
			psa = varData.parray;
			SafeArrayGetLBound(psa, 1, &longlBound);
			SafeArrayGetUBound(psa, 1, &longUBound);

			if(psa->cDims == 1){
				hr = SafeArrayLock(psa);
				if(SUCCEEDED(hr)){
					for(long i = longlBound; i <= longUBound; i++){
						SafeArrayGetElement(psa, &i, &byteData);
						arrayData->Add(byteData);
					}
					SafeArrayUnlock(psa);
					return TRUE;
				}
			}
		}
	}
	return FALSE;
}

BOOL CFileDlg::GetByteDataVariant(BYTE* arrayData, long arrayDataSize, CComVariant* varData)
{
	SAFEARRAYBOUND	rgb[1];
	SAFEARRAY*		psa;
	HRESULT			hr;

	BYTE*			byteData;

	rgb[0].cElements = arrayDataSize;
	rgb[0].lLbound   = 0;

	if(psa = SafeArrayCreate(VT_UI1, 1, rgb)){
		hr = SafeArrayAccessData(psa, (void **)&byteData);
		if(SUCCEEDED(hr)){
			for(long i = 0; i < arrayDataSize; i++)
				byteData[i] = arrayData[i];

			varData->parray = psa;
			varData->vt     = VT_ARRAY | VT_UI1;

			SafeArrayUnaccessData(psa);

			return TRUE;
		}
	}

	return FALSE;
}