/**
    File        : Account.h
    Description : Encapsulates a single account
    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/>.
**/

#ifndef ACCOUNT_H_INCLUDED
#define ACCOUNT_H_INCLUDED

#include <wx/splitter.h>
#include <wx/string.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/statline.h>
#include <wx/textctrl.h>
#include <wx/combobox.h>
#include <wx/checkbox.h>
#include <wx/radiobox.h>
#include <wx/button.h>
//#include <wx/dataview.h>
#include <wx/scrolwin.h>
//#include <wx/file.h>
//#include <wx/ffile.h>
//#include <wx/sstream.h>
#include <wx/tokenzr.h>
//#include <wx/wfstream.h>
//#include <wx/txtstrm.h>
#include <wx/dcclient.h>
#include <wx/dialog.h>
#include <wx/menu.h>
#include <vector>
#include <map>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <wx/stdpaths.h>
#include "Base.h"
#include "Data.h"
#include "settings.h"
#include "IPlugin.h"
#include "BalanceAccount.h"
#include "File.h"
#include "AutoCompleteComboBox.h"
#include "Dialogs.h"

bool SortTransactionsByDate(const STransaction& A, const STransaction& B);

class CAccountManager;
class CAccount;

class CHeader : public wxPanel
{
    public:
    CHeader(wxWindow* pParent, ULONG ID);
    ~CHeader();

    private:
    // id's

    // event handlers
    void OnPaint(wxPaintEvent& paint_event);

    // private data
    wxWindow*           m_pParent;
    CAccount*           m_pAccount;
};

class CTransactionList : public wxScrolledWindow
{
    public:
    CTransactionList(wxWindow* pParent, ULONG ID);
    ~CTransactionList();
    void ToggleHideReconciled();
    void SetScrollPosition(int StartPosition = 0);
    bool IsReconciledHidden()                       { return m_HideReconciled; }

    private:
    int GetNumLinesToDisplay();
    bool HitTest(wxMouseEvent& event, ULONG& RowNumber, STransaction** ppTransaction);

    // id's
    enum
    {
        idViewTransaction,
        idViewImages,
        idEditTransaction,
        idDeleteTransaction,
        idChangeTransactionStatus,
    };

    // event handlers
    void OnDraw(wxDC &DC);
    void OnTransactionLeftClick(wxMouseEvent &event);
    void OnTransactionLeftDoubleClick(wxMouseEvent &event);
    void OnTransactionRightClick(wxMouseEvent &event);
    void OnMouseWheelMovement(wxMouseEvent &event);
    void OnViewImages(wxCommandEvent &event);
    void OnEditTransaction(wxCommandEvent &event);
    void OnDeleteTransaction(wxCommandEvent &event);
    void OnChangeTransactionStatus(wxCommandEvent &event);
    void OnProcessKey(wxKeyEvent &event);

    // private data
    wxWindow*               m_pParent;
    CAccount*               m_pAccount;
    bool                    m_HideReconciled;
    ULONG                   m_yCount;
    std::map<ULONG, ULONG>  m_LineMap;
    STransaction*           m_pCurrentTransaction;
    int                     m_LineHeight;
    int                     m_LinesPerScreen;
};

class CAccount : public wxSplitterWindow, public CAccountBase
{
    public:
    CAccount(wxWindow* pParent, CAccountManagerBase* pAM, IPluginHost* pHost, SAccountInfo& AccountInfo);
    ~CAccount();

    bool LoadTransactionsFromDisk();
    bool SaveTransactionsToDisk();
    bool SaveTransaction(STransaction Transaction, const bool Transfering = false, const bool UpdateDisplay = true);
    STransaction* GetTransaction(const ULONG TransactionNumber);
    CAccountTypePluginBase* GetTransactionRenderer() { return m_pTransactionRenderer; }
    SAccountInfo GetAccountInfo()                    { return m_AccountInfo; }
    void SaveAccountInfo(SAccountInfo& AI)           { m_AccountInfo = AI; }
    const wxString GetAccountName()                  { return m_AccountInfo.AccountName; }
    bool GetAccountLabel(wxString& Label);
    const wxString GetFilename()                     { return m_Filename; }
    const int GetNumberOfAccounts() const            { return m_pAM->GetNumberOfAccounts(); }
    const wxArrayString GetAllAccountNames()         { return m_pAM->GetAccountNames(); }
    void ResetTransactionCounter()                   { m_CurrentTransaction = m_TransactionList.begin(); }
    bool HasMoreTransactions();
    const STransaction& GetNextTransaction();
    ULONG GetLastCheckNum() const                    { return m_LastCheckNum; }
    size_t GetNumTransactions() const                { return m_TransactionList.size(); }
    const double GetLastStatementBalance() const     { return m_AccountInfo.LastStatementBalance; }
    void UpdateBalanceDisplay(const double Balance);
    void UpdateBalances(const bool UpdateDisplay = true);
    void DeleteTransaction(const ULONG TransactionNumber, const bool UseTransferNumber = false);
    ULONG GetNextTransactionNumber()                 { return ++m_LastTransactionNumber; }
    bool IsBalancing()                               { return m_IsBalancing; }
    void StopBalancing();
    void UpdateBalancingStatus(const double Amount, const bool IsDeposit, const bool IsCleared, const bool IsEdit = false);
    void BalancingAccountFinished(wxString DateBalanced);

    // event handlers
    void OnNewTransaction(wxCommandEvent &event);
    void OnToggleHideReconciled(wxCommandEvent &event);
    void OnBalanceAccount(wxCommandEvent &event);
    void OnSearchTransactions(wxCommandEvent &event);
    void OnPrintTransactions(wxCommandEvent &event);
    void OnDisplayAccountDetails(wxCommandEvent &event);

    private:
    void VerifyTransactionRenderer();
    void EnableButtons();
    void DisableButtons();

    // id's
    enum
    {
        idAccountWindow = 300,
        idTopPanel,
        idControlPanel,
        idBottomPanel,
        idHeader,
        idTransactionList,
        idBalanceCtrl,
        idHideReconciledCtrl,
        idNewTransactionBtn,
        idSearchTransactionBtn,
        idPrintTransactionBtn,
        idBalanceAccountBtn,
        idAccountDetailsBtn,
    };

    // child controls
    wxSplitterWindow*                    m_pTopPanel;
    wxPanel*                             m_pControlPanel;
    CBalancePanel*                       m_pBalancePanel;
    wxPanel*                             m_pSearchPanel;
    wxSplitterWindow*                    m_pBottomPanel;
    CHeader*                             m_pHeader;
    CTransactionList*                    m_pTransactionList;
    wxTextCtrl*                          m_pBalanceCtrl;
    wxCheckBox*                          m_pHideReconciledCtrl;

    // private data
    wxWindow*                            m_pParent;
    CAccountManagerBase*                 m_pAM;
    IPluginHost*                         m_pHost;
    CAccountTypePluginBase*              m_pTransactionRenderer;
    wxString                             m_Filename;
    SAccountInfo                         m_AccountInfo;
    std::vector<STransaction>            m_TransactionList;
    std::vector<STransaction>::iterator  m_CurrentTransaction;
    ULONG                                m_LastCheckNum;
    ULONG                                m_LastTransactionNumber;
    bool                                 m_IsBalancing;
    bool                                 m_IsSearching;
    wxString                             m_StatementDate;
    size_t                               m_PageNum;

};

class CNewTransactionDlg : public wxDialog
{
    public:
    CNewTransactionDlg(CAccount* pParent, STransaction& Transaction, const bool IsNew, const bool CanEdit);
    ~CNewTransactionDlg();
    void ShowControls(const ULONG type);
    virtual bool TransferDataFromWindow();

    private:
    // id's
    enum
    {
        idRadioBoxCtrl = 9991,
        idDateCtrl,
        idAmountCtrl,
        idPayeeCtrl,
        idCheckNumCtrl,
        idCategoryCtrl,
        idSubCategoryCtrl,
        idCommentCtrl,
        idTransferAccountCtrl,
    };

    // event handlers
    void OnSave(wxCommandEvent &event);
    void OnCategorySelection(wxCommandEvent &event);
    void OnRadioButtonSelect(wxCommandEvent &event);

    // controls
    wxRadioBox*             m_pRadioBox;
    wxDatePickerCtrl*       m_pDateCtrl;
    wxTextCtrl*             m_pCheckNumCtrl;
    CAutoCompleteComboBox*  m_pPayeeCtrl;
    wxTextCtrl*             m_pAmountCtrl;
    wxComboBox*             m_pCategoryCtrl;
    wxComboBox*             m_pSubCategoryCtrl;
    wxTextCtrl*             m_pCommentCtrl;
    wxStaticText*           m_pTransferAccountText;
    wxComboBox*             m_pTransferAccountCtrl;

    // private data
    CAccount*               m_pAccount;
    STransaction*           m_pTransaction;
    bool                    m_IsNew;
    bool                    m_CanEdit;
    wxString                m_LastRadioBoxSelection;
    wxArrayString           m_TransactionTypeChoices;
    wxArrayString           m_CategoryChoices;
    wxArrayString           m_SubCategoryChoices;
    wxString                m_Amount;
    wxString                m_CheckNumber;
};

#endif // ACCOUNT_H_INCLUDED
