//-----------------------------------------------------------------------------
#ifndef ValuesFromUserDlgH
#define ValuesFromUserDlgH ValuesFromUserDlgH
//-----------------------------------------------------------------------------
#include "DevData.h"
#include <map>
#include <vector>
#include <mvIMPACT_CPP/mvIMPACT_acquire.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam.h>

#include <apps/Common/wxIncludePrologue.h>
#include <wx/wx.h>
#include <wx/filename.h>
#include <wx/imaglist.h>
#include <wx/spinctrl.h>
#include <wx/treectrl.h>
#include <apps/Common/wxIncludeEpilogue.h>

class wxCheckListBox;
class wxSpinCtrl;
class ImageCanvas;
class PropData;
class PropGridFrameBase;

typedef std::map<wxString, wxString> StringToStringMap;

std::string BinaryDataFromString( const std::string& value );
std::string BinaryDataToString( const std::string& value );

//-----------------------------------------------------------------------------
template<class _Tx, typename _Ty>
wxString ReadStringDict( _Tx prop, wxArrayString& choices )
//-----------------------------------------------------------------------------
{
    wxString currentValue;
    if( prop.isValid() )
    {
        currentValue = ConvertedString( prop.readS() );
        std::vector<std::pair<std::string, _Ty> > dict;
        prop.getTranslationDict( dict );
        const typename std::vector<std::pair<std::string, _Ty> >::size_type cnt = dict.size();
        for( typename std::vector<std::pair<std::string, _Ty> >::size_type i = 0; i < cnt; i++ )
        {
            choices.Add( ConvertedString( dict[i].first ) );
        }
    }
    return currentValue;
}

void WriteFile( const void* pBuf, size_t bufSize, const wxString& pathName, wxTextCtrl* pTextCtrl );

//-----------------------------------------------------------------------------
class HEXStringValidator : public wxTextValidator
//-----------------------------------------------------------------------------
{
public:
    HEXStringValidator( wxString* valPtr = NULL );
};

//-----------------------------------------------------------------------------
class OkAndCancelDlg : public wxDialog
//-----------------------------------------------------------------------------
{
    DECLARE_EVENT_TABLE()
protected:
    wxButton*                   pBtnApply_;
    wxButton*                   pBtnCancel_;
    wxButton*                   pBtnOk_;

    virtual void OnBtnApply( wxCommandEvent& ) {}
    virtual void OnBtnCancel( wxCommandEvent& )
    {
        EndModal( wxID_CANCEL );
    }
    virtual void OnBtnOk( wxCommandEvent& )
    {
        EndModal( wxID_OK );
    }
    void AddButtons( wxWindow* pWindow, wxSizer* pSizer, bool boCreateApplyButton = false );
    void FinalizeDlgCreation( wxWindow* pWindow, wxSizer* pSizer );
    //-----------------------------------------------------------------------------
    enum TWidgetIDs
    //-----------------------------------------------------------------------------
    {
        widBtnOk = 1,
        widBtnCancel = 2,
        widBtnApply = 3,
        widFirst = 100
    };
public:
    explicit OkAndCancelDlg( wxWindow* pParent, wxWindowID id, const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE, const wxString& name = wxT( "OkAndCancelDlg" ) );
};

//-----------------------------------------------------------------------------
struct ValueData
//-----------------------------------------------------------------------------
{
    wxString caption_;
    explicit ValueData( const wxString& caption ) : caption_( caption ) {}
    virtual ~ValueData() {}
};

//-----------------------------------------------------------------------------
struct ValueRangeData : public ValueData
//-----------------------------------------------------------------------------
{
    int min_;
    int max_;
    int inc_;
    int def_;
    explicit ValueRangeData( const wxString& caption, int min, int max, int inc, int def ) : ValueData( caption ), min_( min ), max_( max ), inc_( inc ), def_( def ) {}
};

//-----------------------------------------------------------------------------
struct ValueChoiceData : public ValueData
//-----------------------------------------------------------------------------
{
    wxArrayString choices_;
    explicit ValueChoiceData( const wxString& caption, const wxArrayString& choices ) : ValueData( caption ), choices_( choices ) {}
};

//-----------------------------------------------------------------------------
class ValuesFromUserDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    std::vector<wxControl*>     ctrls_;
    std::vector<int>            userInputData_;
public:
    explicit ValuesFromUserDlg( wxWindow* pParent, const wxString& title, const std::vector<ValueData*>& inputData );
    const std::vector<wxControl*>& GetUserInputControls( void ) const
    {
        return ctrls_;
    }
};

//-----------------------------------------------------------------------------
class SettingHierarchyDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    void ExpandAll( wxTreeCtrl* pTreeCtrl );
    void ExpandAllChildren( wxTreeCtrl* pTreeCtrl, const wxTreeItemId& item );
    void PopulateTreeCtrl( wxTreeCtrl* pTreeCtrl, wxTreeItemId currentItem, const wxString& currentItemName, const StringToStringMap& settingRelationships );
public:
    explicit SettingHierarchyDlg( wxWindow* pParent, const wxString& title, const StringToStringMap& settingRelationships );
};

//-----------------------------------------------------------------------------
class DetailedRequestInformationDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    DECLARE_EVENT_TABLE()

    //-----------------------------------------------------------------------------
    enum TWidgetIDs_DetailedRequestInformation
    //-----------------------------------------------------------------------------
    {
        widSCRequestSelector = widFirst
    };

    mvIMPACT::acquire::FunctionInterface* pFI_;
    wxTreeCtrl* pTreeCtrl_;
    wxSpinCtrl* pSCRequestSelector_;

    void ExpandAll( wxTreeCtrl* pTreeCtrl );
    void ExpandAllChildren( wxTreeCtrl* pTreeCtrl, const wxTreeItemId& item );
    void OnSCRequestSelectorChanged( wxSpinEvent& )
    {
        SelectRequest( pSCRequestSelector_->GetValue() );
    }
    void OnSCRequestSelectorTextChanged( wxCommandEvent& )
    {
        SelectRequest( pSCRequestSelector_->GetValue() );
    }
    void PopulateTreeCtrl( wxTreeCtrl* pTreeCtrl, wxTreeItemId parent, Component itComponent );
    void PopulateTreeCtrl( wxTreeCtrl* pTreeCtrl, const int requestNr );
    void SelectRequest( const int requestNr );
public:
    explicit DetailedRequestInformationDlg( wxWindow* pParent, const wxString& title, mvIMPACT::acquire::FunctionInterface* pFI );
};

//-----------------------------------------------------------------------------
class DriverInformationDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    DECLARE_EVENT_TABLE()

    typedef std::map<std::string, std::string> IgnoredInterfacesInfo;

    //-----------------------------------------------------------------------------
    enum TListItemStates
    //-----------------------------------------------------------------------------
    {
        lisUndefined = 0,
        lisChecked = 1,
        lisUnchecked = 2
    };

    //-----------------------------------------------------------------------------
    enum TWidgetIDs_DriverInformationDlg
    //-----------------------------------------------------------------------------
    {
        widTCtrl = widFirst,
        widTClose
    };

    mvIMPACT::acquire::GenICam::SystemModule*   pSystemModule_;
    wxTreeCtrl*                                 pTreeCtrl_;
    wxImageList*                                pIconList_;
    IgnoredInterfacesInfo                       ignoredInterfacesInfo_;
    IgnoredInterfacesInfo                       ignoredInterfacesInfoOriginal_;
    wxString                                    newestMVIAVersionAvailable_;
    wxString                                    newestMVIAVersionInstalled_;

    wxTreeItemId AddComponentListToList( wxTreeItemId parent, mvIMPACT::acquire::ComponentLocator locator, const char* pName );
    void AddStringPropToList( wxTreeItemId parent, mvIMPACT::acquire::ComponentLocator locator, const char* pName );
    void ConfigureItemState( const wxTreeItemId& itemId ) const;
    void ExpandAll( void );
    void ExpandAllChildren( const wxTreeItemId& item );
    std::map<wxString, std::map<wxString, bool> > EnumerateGenICamDevices( unsigned int interfaceIndex, const DeviceManager& devMgr );
    void IgnoreInterfaceTechnologySetting( const std::string& technology, IgnoredInterfacesInfo& interfacesInfo );
    void PopulateTreeCtrl( mvIMPACT::acquire::ComponentIterator itDrivers, const mvIMPACT::acquire::DeviceManager& devMgr );
    void ReadIgnoredInterfacesInfoAndEnableAllInterfaces( void );
    void ReadIgnoredInterfaceTechnologyInfoAndEnableIt( const std::string& technology );
    void UpdateIgnoredInterfacesSettings( IgnoredInterfacesInfo& interfacesInfo );
    void SetParentUndefinedStateIfConflictingChildrenStates( const wxTreeItemId& itemId );
    void UpdateIgnoredInterfacesInfo( const wxTreeItemId& itemId );

    void OnItemStateClick( wxTreeEvent& event );
    virtual void OnBtnCancel( wxCommandEvent& )
    {
        UpdateIgnoredInterfacesSettings( ignoredInterfacesInfoOriginal_ );
        EndModal( wxID_CANCEL );
    }
    virtual void OnClose( wxCloseEvent& )
    {
        UpdateIgnoredInterfacesSettings( ignoredInterfacesInfoOriginal_ );
        EndModal( wxID_CANCEL );
    }
    virtual void OnBtnOk( wxCommandEvent& )
    {
        UpdateIgnoredInterfacesSettings( ignoredInterfacesInfo_ );
        EndModal( wxID_OK );
    }

public:
    ~DriverInformationDlg();
    explicit DriverInformationDlg( wxWindow* pParent, const wxString& title, mvIMPACT::acquire::ComponentIterator itDrivers,
                                   const mvIMPACT::acquire::DeviceManager& devMgr, const wxString& newestMVIAVersionAvailable, const wxString& newestMVIAVersionInstalled );
};

//-----------------------------------------------------------------------------
class UpdatesInformationDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    DECLARE_EVENT_TABLE()

    const StringToStringMap olderDriverVersions_;
    const wxString currentVersion_;
    const wxString newestVersion_;
    const wxString dateReleased_;
    const wxString whatsNew_;
    wxCheckBox* pCBAutoCheckForUpdatesWeekly_;

    virtual void OnClose( wxCloseEvent& )
    {
        EndModal( wxID_CANCEL );
    }
public:
    explicit UpdatesInformationDlg( wxWindow* pParent, const wxString& title, const StringToStringMap& olderDriverVersions,
                                    const wxString& currentVersion, const wxString& newestVersion, const wxString& dateReleased, const wxString& whatsNew, const bool boCurrentAutoUpdateCheckState );
    bool GetAutoCheckForUpdatesWeeklyState( void ) const
    {
        return pCBAutoCheckForUpdatesWeekly_->GetValue();
    }
};

typedef std::map<wxString, PropData*> NameToFeatureMap;

//-----------------------------------------------------------------------------
class FindFeatureDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    DECLARE_EVENT_TABLE()
    PropGridFrameBase* pParent_;
    const NameToFeatureMap& nameToFeatureMap_;
    wxTextCtrl* pTCFeatureName_;
    wxCheckBox* pCBMatchCase_;
    wxListBox* pLBFeatureList_;
    //-----------------------------------------------------------------------------
    enum TWidgetIDs_FindFeatures
    //-----------------------------------------------------------------------------
    {
        widTCFeatureName = widFirst,
        widLBFeatureList,
        widCBMatchCase
    };
    void BuildFeatureList( wxArrayString& features, const bool boMatchCase = false, const wxString& pattern = wxEmptyString ) const;
    void OnFeatureListDblClick( wxCommandEvent& e );
    void OnFeatureListSelect( wxCommandEvent& e )
    {
        SelectFeatureInPropertyGrid( e.GetSelection() );
    }
    void OnFeatureNameTextChanged( wxCommandEvent& )
    {
        UpdateFeatureList();
    }
    void OnMatchCaseChanged( wxCommandEvent& )
    {
        UpdateFeatureList();
    }
    void SelectFeatureInPropertyGrid( const wxString& selection );
    void SelectFeatureInPropertyGrid( const int selection );
    void UpdateFeatureList( void );
public:
    explicit FindFeatureDlg( PropGridFrameBase* pParent, const NameToFeatureMap& nameToFeatureMap, const bool boMatchCaseActive );
    bool GetMatchCase( void ) const
    {
        return pCBMatchCase_->GetValue();
    }
};

//-----------------------------------------------------------------------------
class DetailedFeatureInfoDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    wxTextCtrl* pLogWindow_;
    wxTextAttr fixedPitchStyle_;
    wxTextAttr fixedPitchStyleBold_;
    void AddFeatureInfo( const wxString& infoName, const wxString& info );
    void AddFeatureInfoFromException( const wxString& infoName, const ImpactAcquireException& e );
public:
    explicit DetailedFeatureInfoDlg( wxWindow* pParent, mvIMPACT::acquire::Component comp );
};

//-----------------------------------------------------------------------------
class BinaryDataDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    DECLARE_EVENT_TABLE()
    HEXStringValidator HEXStringValidator_;
    wxTextCtrl* pTCBinaryData_;
    wxTextCtrl* pTCAsciiData_;
    size_t lastDataLength_;
    wxTextAttr fixedPitchStyle_;
    //-----------------------------------------------------------------------------
    enum TWidgetIDs_FindFeatures
    //-----------------------------------------------------------------------------
    {
        widTCBinaryData = widFirst,
        widTCAsciiData
    };
    void OnBinaryDataTextChanged( wxCommandEvent& );
    void ReformatBinaryData( void );
    static void RemoveSeparatorChars( wxString& data );
    void UpdateAsciiData( void );
public:
    explicit BinaryDataDlg( wxWindow* pParent, const wxString& featureName, const wxString& value );
    static size_t FormatData( const wxString& data, wxString& formattedData, const int lineLength, const int fieldLength );
    wxString GetBinaryData( void ) const;
};

//-----------------------------------------------------------------------------
class AssignSettingsToDisplaysDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    std::vector<wxControl*> ctrls_;
public:
    explicit AssignSettingsToDisplaysDlg( wxWindow* pParent, const wxString& title, const std::vector<std::pair<std::string, int> >& settings, const SettingToDisplayDict& settingToDisplayDict, size_t displayCount );
    const std::vector<wxControl*>& GetUserInputControls( void ) const
    {
        return ctrls_;
    }
};

//-----------------------------------------------------------------------------
class RawImageImportDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    PropGridFrameBase* pParent_;
    wxComboBox* pCBPixelFormat_;
    wxComboBox* pCBBayerParity_;
    wxSpinCtrl* pSCWidth_;
    wxSpinCtrl* pSCHeight_;
public:
    explicit RawImageImportDlg( PropGridFrameBase* pParent, const wxString& title, const wxFileName& fileName );
    wxString GetFormat( void ) const;
    wxString GetPixelFormat( void ) const
    {
        return pCBPixelFormat_->GetValue();
    }
    wxString GetBayerParity( void ) const
    {
        return pCBBayerParity_->GetValue();
    }
    long GetWidth( void ) const;
    long GetHeight( void ) const;
};

//-----------------------------------------------------------------------------
class OptionsDlg : public OkAndCancelDlg
//-----------------------------------------------------------------------------
{
    wxCheckListBox* pWarningConfiguration_;
    wxCheckListBox* pAppearanceConfiguration_;
    wxCheckListBox* pPropertyGridConfiguration_;
    wxCheckListBox* pMiscellaneousConfiguration_;
    wxCheckBox* pCBShowQuickSetupOnDeviceOpen_;

public:
    //-----------------------------------------------------------------------------
    enum TWarnings
    //-----------------------------------------------------------------------------
    {
        wWarnOnOutdatedFirmware,
        wWarnOnReducedDriverPerformance,
#if defined(linux) || defined(__linux) || defined(__linux__)
        wWarnOnPotentialNetworkUSBBufferIssues,
#endif // #if defined(linux) || defined(__linux) || defined(__linux__)
        wWarnOnPotentialFirewallIssues,
        wMAX
    };
    //-----------------------------------------------------------------------------
    enum TAppearance
    //-----------------------------------------------------------------------------
    {
        aShowLeftToolBar,
        aShowUpperToolBar,
        aShowStatusBar,
        aMAX
    };
    //-----------------------------------------------------------------------------
    enum TPropertyGrid
    //-----------------------------------------------------------------------------
    {
        pgDisplayToolTips,
        pgUseSelectorGrouping,
        pgPreferDisplayNames,
        pgCreateEditorsWithSlider,
        pgDisplayPropertyIndicesAsHex,
        pgMAX
    };
    //-----------------------------------------------------------------------------
    enum TMiscellaneous
    //-----------------------------------------------------------------------------
    {
        mAllowFastSingleFrameAcquisition,
        mDisplayDetailedInformationOnCallbacks,
        mDisplayMethodExecutionErrors,
        mDisplayFeatureChangeTimeConsumption,
        mMAX
    };
private:
    std::map<TWarnings, bool> initialWarningConfiguration_;
    std::map<TAppearance, bool> initialAppearanceConfiguration_;
    std::map<TPropertyGrid, bool> initialPropertyGridConfiguration_;
    std::map<TMiscellaneous, bool> initialMiscellaneousConfiguration_;
    bool boShowQuickSetupOnDeviceOpen_;

    template<typename _Ty>
    wxStaticBoxSizer* CreateCheckListBox( wxPanel* pPanel, wxBoxSizer* pTopDownSizer, wxCheckListBox** ppCheckListBox, const wxArrayString& choices, const wxString& title, const std::map<_Ty, bool>& initialConfiguration );
    template<typename _Ty>
    void RestoreCheckListBoxStateFromMap( wxCheckListBox* pCheckListBox, const std::map<_Ty, bool>& stateMap );
    template<typename _Ty>
    void StoreCheckListBoxStateToMap( wxCheckListBox* pCheckListBox, std::map<_Ty, bool>& stateMap );
public:
    explicit OptionsDlg( PropGridFrameBase* pParent,
                         const std::map<TWarnings, bool>& initialWarningConfiguration,
                         const std::map<TAppearance, bool>& initialAppearanceConfiguration,
                         const std::map<TPropertyGrid, bool>& initialPropertyGridConfiguration,
                         const std::map<TMiscellaneous, bool>& initialMiscellaneousConfiguration );

    void BackupCurrentState( void );
    wxCheckListBox* GetWarningConfiguration( void ) const
    {
        return pWarningConfiguration_;
    }
    wxCheckListBox* GetAppearanceConfiguration( void ) const
    {
        return pAppearanceConfiguration_;
    }
    wxCheckListBox* GetPropertyGridConfiguration( void ) const
    {
        return pPropertyGridConfiguration_;
    }
    wxCheckListBox* GetMiscellaneousConfiguration( void ) const
    {
        return pMiscellaneousConfiguration_;
    }
    wxCheckBox* GetShowQuickSetupOnDeviceOpenCheckBox( void ) const
    {
        return pCBShowQuickSetupOnDeviceOpen_;
    }
    virtual void OnBtnCancel( wxCommandEvent& )
    {
        EndModal( wxID_CANCEL );
    }
    virtual void OnBtnOk( wxCommandEvent& )
    {
        EndModal( wxID_OK );
    }
    void RestorePreviousState( void );
};

#endif // ValuesFromUserDlgH
