// SendNumericDataToWksDlg.cpp : implementation file
//

#include "stdafx.h"
#include "SendNumericDataToWks.h"
#include "SendNumericDataToWksDlg.h"

//Included for Origin automation server access 
#include "OriginClient.h"

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


/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSendNumericDataToWksDlg dialog

CSendNumericDataToWksDlg::CSendNumericDataToWksDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CSendNumericDataToWksDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CSendNumericDataToWksDlg)
	m_bShowOriginWindow = TRUE;
	m_bExitOriginOnDisconnect = FALSE;
	m_bAppendData = FALSE;
	m_strWksName = _T("Data1");
	m_bSaveProjectOnExit = FALSE;
	m_strFileName = _T("");
	m_nColumns = 2;
	m_nRows = 5;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	//Initialize member variables
	m_nConnOption = USE_EXIST_FIRST;
	m_pClient	  = NULL;		
}

void CSendNumericDataToWksDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSendNumericDataToWksDlg)
	DDX_Control(pDX, IDC_WKS_NAME, m_editWksName);
	DDX_Control(pDX, IDC_SAVE_AS_FILE_NAME, m_editFileName);
	DDX_Control(pDX, IDC_APPEND_DATA, m_btnAppendData);
	DDX_Control(pDX, IDC_SAVE_PROJECT_ON_EXIT, m_btnSaveProject);
	DDX_Control(pDX, IDC_SEND_DATA, m_btnSendData);
	DDX_Control(pDX, IDC_CLEAR_WORKSHEET, m_btnClearWorksheet);
	DDX_Control(pDX, IDC_DISCONNECT_ORIGIN, m_btnDisconnect);
	DDX_Control(pDX, IDC_CONNECT_ORIGIN, m_btnConnect);
	DDX_Check(pDX, IDC_SHOW_ORIGIN_WINDOW, m_bShowOriginWindow);
	DDX_Check(pDX, IDC_EXIT_ORIGIN_ON_DISCONNECT, m_bExitOriginOnDisconnect);
	DDX_Check(pDX, IDC_APPEND_DATA, m_bAppendData);
	DDX_Text(pDX, IDC_WKS_NAME, m_strWksName);
	DDX_Check(pDX, IDC_SAVE_PROJECT_ON_EXIT, m_bSaveProjectOnExit);
	DDX_Text(pDX, IDC_SAVE_AS_FILE_NAME, m_strFileName);
	DDX_Text(pDX, IDC_WKS_COLUMNS, m_nColumns);
	DDX_Text(pDX, IDC_WKS_ROWS, m_nRows);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CSendNumericDataToWksDlg, CDialog)
	//{{AFX_MSG_MAP(CSendNumericDataToWksDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_ALWAYS_CREATE_NEW, OnAlwaysCreateNew)
	ON_BN_CLICKED(IDC_CONNECT_EXISTING_FIRST, OnConnectExistingFirst)
	ON_BN_CLICKED(IDC_CONNECT_ORIGIN, OnConnectOrigin)
	ON_BN_CLICKED(IDC_DISCONNECT_ORIGIN, OnDisconnectOrigin)
	ON_BN_CLICKED(IDC_SHOW_ORIGIN_WINDOW, OnShowOriginWindow)
	ON_BN_CLICKED(IDC_SEND_DATA, OnSendData)
	ON_BN_CLICKED(IDC_CLEAR_WORKSHEET, OnClearWorksheet)
	ON_BN_CLICKED(IDC_SAVE_PROJECT_ON_EXIT, OnSaveProjectOnExit)
	ON_BN_CLICKED(IDC_EXIT_ORIGIN_ON_DISCONNECT, OnExitOriginOnDisconnect)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSendNumericDataToWksDlg message handlers

BOOL CSendNumericDataToWksDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	EnableControls(FALSE);
	
	CButton* pButton = static_cast<CButton*>( GetDlgItem(IDC_CONNECT_EXISTING_FIRST) );
	if( pButton != NULL )
		pButton->SetCheck(BST_CHECKED);	 	
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CSendNumericDataToWksDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CSendNumericDataToWksDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		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;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSendNumericDataToWksDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

/////////////////////////////////////////////////////////////////////////
//Override CDialog methods
/////////////////////////////////////////////////////////////////////////
BOOL CSendNumericDataToWksDlg::DestroyWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	if( m_pClient != NULL )
	{
		delete m_pClient;
		m_pClient = NULL;
	}

	return CDialog::DestroyWindow();
}
		

/////////////////////////////////////////////////////////////////////////
//Private utility functions
/////////////////////////////////////////////////////////////////////////

void CSendNumericDataToWksDlg::EnableControls(BOOL bEnable)
{
	m_btnDisconnect.EnableWindow(bEnable);
	m_btnClearWorksheet.EnableWindow(bEnable);
	m_btnSendData.EnableWindow(bEnable);
	m_btnAppendData.EnableWindow(bEnable);
	m_btnSaveProject.EnableWindow(bEnable);

	m_btnConnect.EnableWindow(!bEnable); 
}



CString CSendNumericDataToWksDlg::GetSaveAsFile()
{
	CString str = "";
	if( !IS_VALID_ORIGIN_PTR(m_pClient) )
		return str;

	_bstr_t bstr;
	bstr =  m_pClient->operator ->()->GetLTStr(_bstr_t("%Y"));
	///str = _com_util::ConvertBSTRToString(bstr);
	str = (LPCTSTR)bstr;

	bstr = 	m_pClient->operator ->()->GetLTStr(_bstr_t("%G"));
	///str += _com_util::ConvertBSTRToString(bstr); 
	str += (LPCTSTR)bstr;

	return str;
}


BOOL CSendNumericDataToWksDlg::ExecuteOriginCMD(LPCSTR lpszCMD)
{
	if( !IS_VALID_ORIGIN_PTR(m_pClient) )
		return FALSE;

	return m_pClient->operator ->()->Execute( _bstr_t(lpszCMD) );
}


/////////////////////////////////////////////////////////////////////////
//Event handler functions for buttons
/////////////////////////////////////////////////////////////////////////	 

void CSendNumericDataToWksDlg::OnConnectOrigin() 
{
	// TODO: Add your control notification handler code here

	//Create a new COriginClient object, which will hold the reference to 
	//an Origin automation server instance 
	m_pClient = new COriginClient(m_nConnOption);
	if( !IS_VALID_ORIGIN_PTR(m_pClient) )
	{
		MessageBox("Failure to access Origin instance", "", MB_OK);

		if( m_pClient != NULL )
		{
			delete m_pClient;
			m_pClient = NULL;
		}

		return;
	}

	//apply the show Origin window option
	OnShowOriginWindow();
	
	//Enable controls after connected to Origin
	EnableControls(TRUE);

	//Origin save as file name
	m_editFileName.SetWindowText( GetSaveAsFile() );

	//Turn on session saving asking block
	ExecuteOriginCMD("doc -ss 1");

	//Seed the random-number generator with current time so that
    //the numbers will be different every time we run.
    srand( (unsigned)time( NULL ) );  
}	  

void CSendNumericDataToWksDlg::OnDisconnectOrigin() 
{
	// TODO: Add your control notification handler code here
	UpdateData();

	if( IS_VALID_ORIGIN_PTR(m_pClient) )
	{
		//Save project if "Save Origin project on exit" option was checked
		if( m_bSaveProjectOnExit )
			m_pClient->operator ->()->Save(_bstr_t(m_strFileName));

		//Exit Origin if the "Exit Origin when Disconnect" option was checked 
		if( m_bExitOriginOnDisconnect )
			m_pClient->operator ->()->Exit();
		delete m_pClient;
		m_pClient = NULL;
	}
	
	//Enable controls after Disconnected from Origin	
	EnableControls(FALSE);
}	


void CSendNumericDataToWksDlg::OnSendData() 
{
	// TODO: Add your control notification handler code here
	if( !IS_VALID_ORIGIN_PTR(m_pClient) )
		return;
	 
	UpdateData();

	//Validate worksheet name
	if( m_strWksName.IsEmpty() )
	{
		MessageBox("Please specify a worksheet name first.", "", MB_OK);
		return;	  
	}

	//Validate m_nColumns and m_nRows 
	if( m_nRows == 0 || m_nColumns == 0 )
	{
		MessageBox("Columns or Rows' value can not be 0.", "", MB_OK);
		return;	  
	}  

	//Check if specified worksheet exists
	WorksheetPtr pwks = m_pClient->operator ->()->FindWorksheet(_bstr_t(m_strWksName));
	if ( pwks == NULL )	//If specified worksheet does not exist then create it
	{
        //If another window has the requested name then our name will be
        //enumerated and the enumerated name will be returned.  So we
        //will put the return value into the edit box in case it is changed.
		_bstr_t bstr = m_pClient->operator ->()->CreatePage(ORIGIN_WINTYPE_WKS, _bstr_t(m_strWksName), _bstr_t("w"));
        ///m_strWksName = _com_util::ConvertBSTRToString(bstr);
		m_strWksName = (LPCTSTR)bstr;

		m_editWksName.SetWindowText(m_strWksName);
	}

	//Get the first target row based on the Append check box
	UINT nRowStart = 0;
	if( m_bAppendData )
	{
		nRowStart = -1;	  //-1 mean append at the end
	}  

	//Make source data
    COleSafeArray csa;
	DWORD bounds[2] = {m_nRows, m_nColumns};
	csa.Create(VT_R8, 2, bounds);

	long index[2];
	UINT nLowerBound = 0;
	UINT nUpperBound = m_nRows;

	for( UINT ii=0; ii < m_nColumns; ii++ )
	{ 	
		for( UINT jj=0; jj < m_nRows; jj++ )
		{					
			index[0]=jj;
			index[1]=ii;

			double fVal = 0.0;
			if( ii == 0 )
				fVal = nLowerBound + jj + 1;
			else
				fVal = ((nLowerBound + jj + 1) * 10 + ii) * rand()/RAND_MAX;
			
			csa.PutElement(index, &fVal);			
		}
	} 	

	//Put generated numeric data into Origin
	m_pClient->SetWorksheet(m_strWksName, csa, nRowStart);

}

void CSendNumericDataToWksDlg::OnClearWorksheet() 
{
	// TODO: Add your control notification handler code here
	if( !IS_VALID_ORIGIN_PTR(m_pClient) )
		return;

	UpdateData();

	CString str = "clearworksheet " + m_strWksName;	      
	ExecuteOriginCMD(str);
}


/////////////////////////////////////////////////////////////////////////
//Event handler functions for check boxes or radio buttons
/////////////////////////////////////////////////////////////////////////  
void CSendNumericDataToWksDlg::OnAlwaysCreateNew() 
{
	// TODO: Add your control notification handler code here
	m_nConnOption = ALWAYS_CREATE_NEW;

}

void CSendNumericDataToWksDlg::OnConnectExistingFirst() 
{
	// TODO: Add your control notification handler code here
	m_nConnOption = USE_EXIST_FIRST;
}	 


void CSendNumericDataToWksDlg::OnShowOriginWindow() 
{
	// TODO: Add your control notification handler code here
	if( !IS_VALID_ORIGIN_PTR(m_pClient) )
		return;

	UpdateData();
	
	//CString strCMD = "doc -mk ";
	//strCMD += m_bShowOriginWindow ? "1" : "0";	
	
	//ExecuteOriginCMD(strCMD);
	if( m_bShowOriginWindow )
		m_pClient->operator->()->Visible = OrgApplication::MAINWND_SHOW_BRING_TO_FRONT;
	else
		m_pClient->operator->()->Visible = OrgApplication::MAINWND_HIDE;
}


void CSendNumericDataToWksDlg::OnSaveProjectOnExit() 
{
	// TODO: Add your control notification handler code here
	UpdateData();

	m_editFileName.EnableWindow(m_bSaveProjectOnExit);	
}

void CSendNumericDataToWksDlg::OnExitOriginOnDisconnect() 
{
	// TODO: Add your control notification handler code here
	UpdateData();
}
