/**
    File        : Main.cpp
    Description : main entry point for Savings plugin
    Author      : Raymond Marsh
    Created     : 08/01/2009
    Copyright 2009, 2010 Raymond Marsh

    This program is distributed under the terms of the GNU General Public License.
    To view a copy of the license see the file 'copying.txt'

    This file is part of the Ace Personal Finance Assistant Suite.

    Ace Personal Finance Assistant is free software: you can redistribute it and/or modify it under
    the terms of the GNU General Public License as published by the Free Software Foundation, either
    version 3 of the License, or (at your option) any later version.

    Ace Personal Finance Assistant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
    without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along with Ace Personal Finance Assistant.
    If not, see <http://www.gnu.org/licenses/>.
**/

#include "Main.h"
/* aparently a DllMain function is not needed after all.......
#ifdef __WXMSW__
__declspec(dllimport) void wxSetInstance(HINSTANCE hInst);
bool APIENTRY DllMain(HANDLE hModule, DWORD ReasonForCall, LPVOID lpReserved)
{
    switch(ReasonForCall)
    {
        case DLL_PROCESS_ATTACH:
        if(wxTheApp == NULL)
            wxInitialize();
        break;

        case DLL_THREAD_ATTACH:
        break;

        case DLL_THREAD_DETACH:
        break;

        case DLL_PROCESS_DETACH:
        wxUninitialize();
        break;
    }
    return TRUE;
}
#endif // __WXMSW__
*/

bool RegisterPlugin(IPlugin **ppPluginInterface)
{
    // do nothing if the plugin interface is not NULL
    wxCHECK_MSG(*ppPluginInterface == NULL,
                false,
                _("Interface pointer must be NULL") );

    CSavings *pPlugin = new CSavings;
    *ppPluginInterface = pPlugin;
    return true;
}

bool UnregisterPlugin(IPlugin **ppPluginInterface)
{
    // do not try to delete a NULL pointer
    wxCHECK_MSG(*ppPluginInterface != NULL,
                false,
                _("Interface pointer must NOT be NULL") );

    delete (*ppPluginInterface);
    *ppPluginInterface = NULL;
    return true;
}

CSavings::CSavings()
: m_pHost(NULL), m_pData(NULL), m_PluginName(_("Savings") ), m_PluginWeight(2),
  m_pTransaction(NULL)
{
    // these controls must be checked for non-null and manually deleted in
    // ::ShutdownPlugin if they are non-null
    m_pTransactionViewer = NULL;
}

CSavings::~CSavings()
{

}

void CSavings::InitializePlugin(IPluginHost* pHost)
{
    m_pHost = pHost;
    m_pData = m_pHost->GetGlobalDataObject();
}

void CSavings::ShutdownPlugin()
{
    if (m_pTransactionViewer)
    {
        delete m_pTransactionViewer;
        m_pTransactionViewer = NULL;
    }
}

int CSavings::GetHeaderToDisplay(std::vector<std::pair<wxString, int> >& Header)
{
    Header.push_back(std::make_pair(_("TYPE"),     35) );
    Header.push_back(std::make_pair(_("DATE"),    110) );
    Header.push_back(std::make_pair(_("CK #"),    245) );
    Header.push_back(std::make_pair(_("PAYEE"),   350) );
    Header.push_back(std::make_pair(_("R"),       795) );
    Header.push_back(std::make_pair(_("DEBIT"),   825) );
    Header.push_back(std::make_pair(_("DEPOSIT"), 950) );
    Header.push_back(std::make_pair(_("TOTAL"),  1075) );
    return Header.size();
}

int CSavings::GetItemsToDisplay(const STransaction& Transaction, wxArrayString& List, std::vector<int>& Pos)
{
    Pos.push_back(35);
    Pos.push_back(110);
    Pos.push_back(245);
    Pos.push_back(350);
    Pos.push_back(795);
    Pos.push_back(825);
    Pos.push_back(950);
    Pos.push_back(1075);

    wxString s = m_pData->GetTransactionTypeString(Transaction.Type);
    List.Add(s);

    List.Add(Transaction.Date);
    if (Transaction.CheckNumber == 0)
    {
        List.Add(_(" ") );
    }
    else
    {
        List.Add(wxString::Format(_("%u"), Transaction.CheckNumber) );
    }
    List.Add(Transaction.Payee);
//    wxMessageBox(wxString::Format("%u", Transaction.Status) );
    switch (Transaction.Status)
    {
        case TS_OPEN:
        List.Add(_(" ") );
        break;

        case TS_CLEARED:
        List.Add(_("C") );
        break;

        case TS_RECONCILED:
        List.Add(_("R") );
        break;

        default:
        wxFAIL_MSG(wxString::Format(_("Invalid Transaction Status Code\nStatus ID = %u"), Transaction.Status) );
    }
    if (Transaction.IsDeposit)
    {
        List.Add(_(" ") );
        List.Add(wxString::Format(_("%1.2f"), Transaction.Amount) );
    }
    else
    {
        List.Add(wxString::Format(_("%1.2f"), Transaction.Amount) );
        List.Add(_(" ") );
    }
    List.Add(wxString::Format(_("%1.2f"), Transaction.Balance) );

    return (int)List.GetCount();
}

int CSavings::GetTransactionViewer(wxString Title, STransaction& Transaction,
                                    bool IsNewTransaction, bool CanEditTransaction)
{
    // delete any previous instances of the transaction viewer to prevent memry leaks!
    if (m_pTransactionViewer)
    {
        delete m_pTransactionViewer;
        m_pTransactionViewer = NULL;
    }

    m_pTransaction = &Transaction;

    // get some new ID's from the host
    const long ID_DIALOG           = m_pHost->GetNewId();
    const long IDC_TRANSACTIONDATE = m_pHost->GetNewId();
    const long IDC_AMOUNT          = m_pHost->GetNewId();
    const long IDC_PAYEE           = m_pHost->GetNewId();
    const long IDC_CHECKNUM        = m_pHost->GetNewId();
    const long IDC_CATEGORY        = m_pHost->GetNewId();
    const long IDC_SUBCATEGORY     = m_pHost->GetNewId();
    const long IDC_COMMENT         = m_pHost->GetNewId();

    // create the dialog window
    m_pTransactionViewer = new wxDialog(NULL,
                                        ID_DIALOG,
                                        Title,
                                        wxDefaultPosition,
                                        wxSize(300, 400),
                                        wxCAPTION);

    // set starting transaction date and amount
    wxDateTime StartDate;
    if (IsNewTransaction)
    {
        m_Amount = _("");
        StartDate = wxDateTime::Today();
    }
    else
    {
        m_Amount = wxString::Format(_("%#1.2f"), Transaction.Amount);
        if (StartDate.ParseDate(Transaction.Date) == NULL)
        {
            wxFAIL_MSG(_("wxDateTime::ParseDate() returned NULL") );
        }
    }

    // get list of categories
    m_pData->GetAllCategories(m_CategoryChoices);

    // set up data entry text boxes
    wxGridSizer *pGSizer = new wxGridSizer(0, 2, 5, 5);

    switch (Transaction.Type)
    {
        case TT_START:
        {
        // transaction date *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Date") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pDateCtrl = new wxDatePickerCtrl(m_pTransactionViewer,
                                                            IDC_TRANSACTIONDATE,
                                                            StartDate,
                                                            wxDefaultPosition,
                                                            wxDefaultSize,
                                                            wxDP_DROPDOWN,
                                                            wxDefaultValidator),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Date) );
        }

        // amount *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Amount") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pAmountCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                        IDC_AMOUNT,
                                                        m_Amount,
                                                        wxDefaultPosition,
                                                        wxDefaultSize,
                                                        0,
                                                        wxTextValidator(wxFILTER_NUMERIC,
                                                                        &m_Amount) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY,
                                          wxString::Format(_("$%#1.2f"), Transaction.Amount) ) );
        }

        // category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Starting Balance") ) );

        // sub-category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Sub Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _(" ") ) );

        // comments
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Comments") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _(" ") ) );
        pGSizer->AddStretchSpacer(3);
        }
        break;//////////////////////////////////////////////////////////////////

        case TT_CHECK:
        {
        // transaction date *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Date") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pDateCtrl = new wxDatePickerCtrl(m_pTransactionViewer,
                                                            IDC_TRANSACTIONDATE,
                                                            StartDate,
                                                            wxDefaultPosition,
                                                            wxDefaultSize,
                                                            wxDP_DROPDOWN,
                                                            wxDefaultValidator),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Date) );
        }

        // payee
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Payee") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pPayeeCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                       IDC_PAYEE,
                                                       _(""),
                                                       wxDefaultPosition,
                                                       wxDefaultSize,
                                                       0,
                                                       wxTextValidator(wxFILTER_ASCII,
                                                                       &Transaction.Payee) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Payee) );
        }

        // check number *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Check #") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pCheckNumCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                          IDC_CHECKNUM,
                                                          _(""),
                                                          wxDefaultPosition,
                                                          wxDefaultSize,
                                                          0,
                                                          wxTextValidator(wxFILTER_NUMERIC,
                                                                          &m_CheckNumber) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY,
                                          wxString::Format(_("%u"), Transaction.CheckNumber) ) );
        }

        // amount *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Amount") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pAmountCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                        IDC_AMOUNT,
                                                        _(""),
                                                        wxDefaultPosition,
                                                        wxDefaultSize,
                                                        0,
                                                        wxTextValidator(wxFILTER_NUMERIC,
                                                                        &m_Amount) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY,
                                          wxString::Format(_("$%#1.2f"), Transaction.Amount) ) );
        }

        // category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pCategoryCtrl = new wxComboBox(m_pTransactionViewer,
                                                          IDC_CATEGORY,
                                                          _(""),
                                                          wxDefaultPosition,
                                                          wxDefaultSize,
                                                          m_CategoryChoices,
                                                          0,
                                                          wxGenericValidator(&Transaction.Category) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Category) );
        }

        // sub-category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Sub Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pSubCategoryCtrl = new wxComboBox(m_pTransactionViewer,
                                                             IDC_SUBCATEGORY,
                                                             _(""),
                                                             wxDefaultPosition,
                                                             wxDefaultSize,
                                                             m_SubCategoryChoices,
                                                             0,
                                                             wxGenericValidator(&Transaction.SubCategory) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.SubCategory) );
        }

        // comments
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Comments") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pCommentCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                         IDC_COMMENT,
                                                         _(""),
                                                         wxDefaultPosition,
                                                         wxDefaultSize,
                                                         0,
                                                         wxTextValidator(wxFILTER_ASCII,
                                                                         &Transaction.Comment) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Comment) );
        }
        pGSizer->AddStretchSpacer(1);
        }
        break;//////////////////////////////////////////////////////////////////

        case TT_DEBIT:
        {
        // transaction date *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Date") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pDateCtrl = new wxDatePickerCtrl(m_pTransactionViewer,
                                                            IDC_TRANSACTIONDATE,
                                                            StartDate,
                                                            wxDefaultPosition,
                                                            wxDefaultSize,
                                                            wxDP_DROPDOWN,
                                                            wxDefaultValidator),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Date) );
        }

        // payee
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Payee") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pPayeeCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                       IDC_PAYEE,
                                                       _(""),
                                                       wxDefaultPosition,
                                                       wxDefaultSize,
                                                       0,
                                                       wxTextValidator(wxFILTER_ASCII,
                                                                       &Transaction.Payee) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Payee) );
        }

        // amount *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Amount") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pAmountCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                        IDC_AMOUNT,
                                                        _(""),
                                                        wxDefaultPosition,
                                                        wxDefaultSize,
                                                        0,
                                                        wxTextValidator(wxFILTER_NUMERIC,
                                                                        &m_Amount) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY,
                                          wxString::Format(_("$%#1.2f"), Transaction.Amount) ) );
        }

        // category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pCategoryCtrl = new wxComboBox(m_pTransactionViewer,
                                                          IDC_CATEGORY,
                                                          _(""),
                                                          wxDefaultPosition,
                                                          wxDefaultSize,
                                                          m_CategoryChoices,
                                                          0,
                                                          wxGenericValidator(&Transaction.Category) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Category) );
        }

        // sub-category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Sub Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pSubCategoryCtrl = new wxComboBox(m_pTransactionViewer,
                                                             IDC_SUBCATEGORY,
                                                             _(""),
                                                             wxDefaultPosition,
                                                             wxDefaultSize,
                                                             m_SubCategoryChoices,
                                                             0,
                                                             wxGenericValidator(&Transaction.SubCategory) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.SubCategory) );
        }

        // comments
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Comments") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pCommentCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                         IDC_COMMENT,
                                                         _(""),
                                                         wxDefaultPosition,
                                                         wxDefaultSize,
                                                         0,
                                                         wxTextValidator(wxFILTER_ASCII,
                                                                         &Transaction.Comment) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Comment) );
        }
        pGSizer->AddStretchSpacer(2);
        }
        break;//////////////////////////////////////////////////////////////////

        case TT_DEPOSIT:
        {
        // transaction date *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Date") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pDateCtrl = new wxDatePickerCtrl(m_pTransactionViewer,
                                                            IDC_TRANSACTIONDATE,
                                                            StartDate,
                                                            wxDefaultPosition,
                                                            wxDefaultSize,
                                                            wxDP_DROPDOWN,
                                                            wxDefaultValidator),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Date) );
        }

        // from
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("From") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pPayeeCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                       IDC_PAYEE,
                                                       _(""),
                                                       wxDefaultPosition,
                                                       wxDefaultSize,
                                                       0,
                                                       wxTextValidator(wxFILTER_ASCII,
                                                                       &Transaction.Payee) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Payee) );
        }

        // amount *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Amount") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pAmountCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                        IDC_AMOUNT,
                                                        _(""),
                                                        wxDefaultPosition,
                                                        wxDefaultSize,
                                                        0,
                                                        wxTextValidator(wxFILTER_NUMERIC,
                                                                        &m_Amount) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY,
                                          wxString::Format(_("$%#1.2f"), Transaction.Amount) ) );
        }

        // category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pCategoryCtrl = new wxComboBox(m_pTransactionViewer,
                                                          IDC_CATEGORY,
                                                          _(""),
                                                          wxDefaultPosition,
                                                          wxDefaultSize,
                                                          m_CategoryChoices,
                                                          0,
                                                          wxGenericValidator(&Transaction.Category) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Category) );
        }

        // sub-category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Sub Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pSubCategoryCtrl = new wxComboBox(m_pTransactionViewer,
                                                             IDC_SUBCATEGORY,
                                                             _(""),
                                                             wxDefaultPosition,
                                                             wxDefaultSize,
                                                             m_SubCategoryChoices,
                                                             0,
                                                             wxGenericValidator(&Transaction.SubCategory) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.SubCategory) );
        }

        // comments
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Comments") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pCommentCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                         IDC_COMMENT,
                                                         _(""),
                                                         wxDefaultPosition,
                                                         wxDefaultSize,
                                                         0,
                                                         wxTextValidator(wxFILTER_ASCII,
                                                                         &Transaction.Comment) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Comment) );
        }
        pGSizer->AddStretchSpacer(2);
        }
        break;//////////////////////////////////////////////////////////////////

        case TT_ATM:
        {
        // transaction date *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Date") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pDateCtrl = new wxDatePickerCtrl(m_pTransactionViewer,
                                                            IDC_TRANSACTIONDATE,
                                                            StartDate,
                                                            wxDefaultPosition,
                                                            wxDefaultSize,
                                                            wxDP_DROPDOWN,
                                                            wxDefaultValidator),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Date) );
        }

        // amount *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Amount") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pAmountCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                        IDC_AMOUNT,
                                                        _(""),
                                                        wxDefaultPosition,
                                                        wxDefaultSize,
                                                        0,
                                                        wxTextValidator(wxFILTER_NUMERIC,
                                                                        &m_Amount) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY,
                                          wxString::Format(_("$%#1.2f"), Transaction.Amount) ) );
        }

        // category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("ATM Withdrawal") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);

        // sub-category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Sub Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pSubCategoryCtrl = new wxComboBox(m_pTransactionViewer,
                                                             IDC_SUBCATEGORY,
                                                             _(""),
                                                             wxDefaultPosition,
                                                             wxDefaultSize,
                                                             m_SubCategoryChoices,
                                                             0,
                                                             wxGenericValidator(&Transaction.SubCategory) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.SubCategory) );
        }

        // comments
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Comments") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pCommentCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                         IDC_COMMENT,
                                                         _(""),
                                                         wxDefaultPosition,
                                                         wxDefaultSize,
                                                         0,
                                                         wxTextValidator(wxFILTER_ASCII,
                                                                         &Transaction.Comment) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Comment) );
        }
        pGSizer->AddStretchSpacer(3);
        }
        break;//////////////////////////////////////////////////////////////////

        case TT_TRANSFER:
        {
        // transaction date *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Date") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pDateCtrl = new wxDatePickerCtrl(m_pTransactionViewer,
                                                            IDC_TRANSACTIONDATE,
                                                            StartDate,
                                                            wxDefaultPosition,
                                                            wxDefaultSize,
                                                            wxDP_DROPDOWN,
                                                            wxDefaultValidator),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Date) );
        }

        // from
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("To") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Payee) );

        // amount *** Manually transfer this data ***
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Amount") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pAmountCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                        IDC_AMOUNT,
                                                        _(""),
                                                        wxDefaultPosition,
                                                        wxDefaultSize,
                                                        0,
                                                        wxTextValidator(wxFILTER_NUMERIC,
                                                                        &m_Amount) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY,
                                          wxString::Format(_("$%#1.2f"), Transaction.Amount) ) );
        }

        // category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        Transaction.Category = _("Account Transfer");
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Category) );

        // sub-category
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Sub Category") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pSubCategoryCtrl = new wxComboBox(m_pTransactionViewer,
                                                             IDC_SUBCATEGORY,
                                                             _(""),
                                                             wxDefaultPosition,
                                                             wxDefaultSize,
                                                             m_SubCategoryChoices,
                                                             0,
                                                             wxGenericValidator(&Transaction.SubCategory) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.SubCategory) );
        }

        // comments
        pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, _("Comments") ),
                     1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        if (CanEditTransaction)
        {
            pGSizer->Add(m_pCommentCtrl = new wxTextCtrl(m_pTransactionViewer,
                                                         IDC_COMMENT,
                                                         _(""),
                                                         wxDefaultPosition,
                                                         wxDefaultSize,
                                                         0,
                                                         wxTextValidator(wxFILTER_ASCII,
                                                                         &Transaction.Comment) ),
                         1, wxEXPAND | wxTOP | wxBOTTOM, 3);
        }
        else
        {
            pGSizer->Add(new wxStaticText(m_pTransactionViewer, wxID_ANY, Transaction.Comment) );
        }
        pGSizer->AddStretchSpacer(2);
        }
        break;//////////////////////////////////////////////////////////////////

        default:
        wxFAIL_MSG(_("Invalid transaction type in module : Checking") );
    }

    /// TODO: change save and cancel buttons to wxStdBtnSizer

    // set up the buttons
    wxStdDialogButtonSizer* pBtnSizer = new wxStdDialogButtonSizer();
    if (CanEditTransaction)
    {
        pBtnSizer->AddButton(new wxButton(m_pTransactionViewer, wxID_OK, _("OK") ) );
        pBtnSizer->AddButton(new wxButton(m_pTransactionViewer, wxID_CANCEL, _("Cancel") ) );
    }
    else
    {
        pBtnSizer->AddButton(new wxButton(m_pTransactionViewer, wxID_CANCEL, _("Cancel") ) );
    }
    pBtnSizer->Realize();

    // put everything together
    wxBoxSizer *pVSizer  = new wxBoxSizer(wxVERTICAL);
    pVSizer->Add(pGSizer, 5, wxEXPAND | wxALL, 10);
    pVSizer->Add(new wxStaticLine(m_pTransactionViewer), 0, wxEXPAND | wxALL, 5);
    pVSizer->Add(pBtnSizer, 1, wxEXPAND | wxALL, 10);
    m_pTransactionViewer->SetSizer(pVSizer);

    if (CanEditTransaction)
    {
        switch(Transaction.Type)
        {
            case TT_CHECK:
            case TT_DEBIT:
            case TT_DEPOSIT:
            m_pPayeeCtrl->SetFocus();
            break;

            case TT_ATM:
            case TT_TRANSFER:
            m_pAmountCtrl->SetFocus();
            break;
        }

        // attach handlers
        // buttons
        m_pTransactionViewer->Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED,
                wxCommandEventHandler(CSavings::OnTransactionViewerButtonOK), NULL, this);
        m_pTransactionViewer->Connect(wxID_CANCEL, wxEVT_COMMAND_BUTTON_CLICKED,
                wxCommandEventHandler(CSavings::OnTransactionViewerButtonCancel), NULL, this);
        // category selection
        m_pTransactionViewer->Connect(IDC_CATEGORY, wxEVT_COMMAND_COMBOBOX_SELECTED,
                wxCommandEventHandler(CSavings::OnTransactionViewerCategorySelection), NULL, this);
    }
    else
    {
        Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED,
                wxCommandEventHandler(CSavings::OnTransactionViewerButtonCancel) );
    }
    return m_pTransactionViewer->ShowModal();
}

void CSavings::OnTransactionViewerButtonOK(wxCommandEvent &event)
{
/*
wxString str = wxString::Format("%u\n%u\n%s\n%s\n%u\n%u\n%s\n%1.2f\n%s\n%s\n%s\n%u\n--",
                                    m_pTransaction->TransactionNumber,
                                    m_pTransaction->TransferNumber,
                                    m_pTransaction->AccountName,
                                    m_pTransaction->Date,
                                    m_pTransaction->Type,
                                    m_pTransaction->CheckNumber,
                                    m_pTransaction->Payee,
                                    m_pTransaction->Amount,
                                    m_pTransaction->Category,
                                    m_pTransaction->SubCategory,
                                    m_pTransaction->Comment,
                                    m_pTransaction->Status);
wxMessageBox(str, "transaction - plugin, before", wxOK);
*/
    // make sure dollar amount is an accepted value (x.xx)
    wxString strAmount = m_pAmountCtrl->GetValue();
    if (!m_pData->VerifyCorrectAmountFormat(strAmount) )
    {
        return;
    }

    if (m_pTransactionViewer->Validate() && m_pTransactionViewer->TransferDataFromWindow() )
    {
        // date
        wxString strDate = (m_pDateCtrl->GetValue() ).Format(_("%m/%d/%Y") );
        m_pTransaction->Date = strDate;
        // check number
        if (m_pTransaction->Type == TT_CHECK)
        {
            if (!(m_pCheckNumCtrl->GetValue() ).ToULong(&m_pTransaction->CheckNumber) )
            {
                m_pTransaction->CheckNumber = 0;
            }
        }
        // payee is ATM
        if(m_pTransaction->Type == TT_ATM)
        {
            m_pTransaction->Payee = _("ATM Withdrawal");
        }
        strAmount.ToDouble(&m_pTransaction->Amount);
        if (m_pTransaction->Category.IsEmpty() ) m_pTransaction->Category = _(" ");
        if (m_pTransaction->SubCategory.IsEmpty() ) m_pTransaction->SubCategory = _(" ");
        if (m_pTransaction->Comment.IsEmpty() ) m_pTransaction->Comment = _(" ");

        // check for unacceptable entries
        wxString str;
        if (m_pTransaction->Type == TT_CHECK)
            if (m_pTransaction->CheckNumber == 0)
                str.Append(_("> 'Check Number'\n") );
        if (m_pTransaction->Payee.IsEmpty() )
            str.Append(_("> 'Payee'\n") );
        if (m_pTransaction->Amount < 0)
            str.Append(_("> 'Amount'\n") );
        if (!str.IsEmpty() )
        {
            wxMessageBox(wxString::Format(_("Item(s)\n%sCannot be empty!"), str),
                         _("ERROR"),
                         wxOK | wxICON_ERROR,
                         m_pTransactionViewer);
            return;
        }
        m_pTransactionViewer->EndModal(wxID_OK);
    }
    else
    {
        wxFAIL_MSG(_("Could not validate data!") );
    }
}

void CSavings::OnTransactionViewerButtonCancel(wxCommandEvent &event)
{
    m_pTransactionViewer->EndModal(wxID_CANCEL);
}

void CSavings::OnTransactionViewerCategorySelection(wxCommandEvent &event)
{
    wxArrayString SubCategoryChoices;
    if (m_pSubCategoryCtrl->GetCount() != 0)
        m_pSubCategoryCtrl->Clear();
    wxString Category = m_pCategoryCtrl->GetValue();
    m_pData->GetAllSubCategories(Category, SubCategoryChoices);
    m_pSubCategoryCtrl->Append(SubCategoryChoices);
}

