//-----------------------------------------------------------------------------
#ifndef DeviceHandlerBlueDeviceH
#define DeviceHandlerBlueDeviceH DeviceHandlerBlueDeviceH
//-----------------------------------------------------------------------------
#include <common/auto_array_ptr.h>
#include "DeviceHandler.h"
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam_FileStream.h>
#include "PackageDescriptionParser.h"

class wxProgressDialog;

//-----------------------------------------------------------------------------
class DeviceHandlerBlueDevice : public DeviceHandler
//-----------------------------------------------------------------------------
{
    enum TProductGroup
    {
        pgUnknown,
        pgBlueCOUGAR_P,
        pgBlueCOUGAR_S,
        pgBlueCOUGAR_X,
        pgBlueCOUGAR_Y,
        pgBlueFOX3,
        pgBlueLYNX_M7
    };
    TProductGroup product_;
    wxString firmwareUpdateFileName_;
    wxString firmwareUpdateFileFilter_;
    wxString firmwareUpdateFolder_;
    wxString firmwareUpdateDefaultFolder_;
    wxString firmwareUpdateFolderDevelopment_;
    wxString GenICamFile_;
    static wxString packageDescriptionBCX_;
    static wxString packageDescriptionBF3_;
    wxString temporaryFolder_;

    int                                 CheckForIncompatibleFirmwareVersions_BlueCOUGAR_X( bool boSilentMode, const wxString& serial, const FileEntryContainer& fileEntries, const wxString& selection, const Version& currentFirmwareVersion );
    void                                DetermineValidFirmwareChoices( const wxString& productFromManufacturerInfo, const wxString& product, const FileEntryContainer& fileEntries, const FileEntryContainer::size_type cnt, const Version& deviceVersion, wxArrayString& choices, wxArrayString& unusableFiles );
    TUpdateResult                       DoFirmwareUpdate_BlueCOUGAR_XOrY( bool boSilentMode, const wxString& serial, const char* pBuf, const size_t bufSize, const Version& currentFirmwareVersion );
    TUpdateResult                       DoFirmwareUpdate_BlueFOX3( bool boSilentMode, const wxString& serial, const char* pBuf, const size_t bufSize );
    bool                                ExtractFileVersion( const wxString& fileName, Version& fileVersion ) const;
    static bool                         GetFileFromArchive( const wxString& firmwareFileAndPath, const char* pArchive, size_t archiveSize, const wxString& filename, auto_array_ptr<char>& data, DeviceConfigureFrame* pParent );
    wxString                            GetFullyQualifiedPathForUserSetBackup( void ) const
    {
        return temporaryFolder_ + wxString( pDev_->serial.readS().c_str(), wxConvUTF8 ) + wxT( ".xml" );
    }
    int                                 GetLatestFirmwareVersionCOUGAR_XAndYOrFOX3Device( Version& latestFirmwareVersion ) const;
    wxString                            GetProductFromManufacturerInfo( void ) const;
    std::vector<std::map<wxString, SuitableProductKey>::const_iterator> GetSuitableFirmwareIterators( const FileEntry& entry, const wxString& product, const wxString& productFromManufacturerInfo ) const;
    static bool                         IsXAS( const wxString& manufacturerSpecificInformation )
    {
        const wxArrayString tokens = wxSplit( manufacturerSpecificInformation, wxT( '-' ) );
        if( tokens.Count() == 4 )
        {
            if( ( tokens[0].length() == 3 ) &&
                ( tokens[1].length() == 6 ) &&
                ( tokens[2].length() == 6 ) &&
                ( tokens[3].length() == 4 ) &&
                ( tokens[3].find( "XAS" ) == 0 ) )
            {
                return true;
            }
        }
        return false;
    }
    bool                                IsBlueCOUGAR_X( void ) const;
    bool                                IsBlueCOUGAR_X_XAS( void ) const
    {
        const wxString token = GetProductFromManufacturerInfo();
        if( token.StartsWith( wxT( "X" ) ) && token.Contains( wxT( "9XAS1" ) ) ) // initial nomenclature
        {
            return true;
        }
        return IsXAS( token );
    }
    bool                                IsBlueCOUGAR_Y( void ) const;
    bool                                IsBlueFOX3( void ) const
    {
        return( ( ConvertedString( pDev_->family.read() ).Find( wxT( "mvBlueFOX3" ) ) == wxNOT_FOUND ) &&
                !isBlueFOX3_XAS() ) ? false : true;
    }
    bool                                isBlueFOX3_XAS( void ) const
    {
        const wxString token = GetProductFromManufacturerInfo();
        if( token.StartsWith( wxT( "2" ) ) && token.Contains( wxT( "9XAS1" ) ) ) // initial nomenclature
        {
            return true;
        }
        return IsXAS( token );
    }
    bool                                IsBlueSIRIUS( void ) const
    {
        return pDev_->product.read().find( "mvBlueSIRIUS" ) != std::string::npos;
    }
    bool                                IsFirmwareUpdateMeaningless( bool boSilentMode, const Version& deviceFWVersion, const Version& selectedFWVersion, const wxString& defaultFWArchive, const Version& defaultFolderFWVersion ) const;
    bool                                IsMatrixVisionGEVDeviceRunningWithNormalFirmware( void ) const;
    static TUpdateResult                ParseUpdatePackageCOUGAR_XOrFOX3Device( PackageDescriptionFileParser& fileParser, const wxString& firmwareFileAndPath, DeviceConfigureFrame* pParent, auto_array_ptr<char>& pBuffer );
    void                                RebootDevice( bool boSilentMode, const wxString& serial );
    static void                         RunThreadAndShowProgress( wxThread* pThread, wxProgressDialog* pDlg, unsigned long threadInterval_ms, int maxExecutionTime_ms );
    void                                SelectCustomGenICamFile( const wxString& descriptionFile = wxEmptyString );
    wxString                            SetUserSetDefault( const wxString& userSetDefaultValue );
    int                                 UpdateCOUGAR_SDevice( bool boSilentMode );
    int                                 UpdateCOUGAR_XOrYOrFOX3Device( bool boSilentMode, bool boPersistentUserSets );
    int                                 UpdateLYNX_M7OrCOUGAR_PDevice( bool boSilentMode );
    int                                 UploadFile( const wxString& fullPath, const wxString& descriptionFile );
    TUpdateResult                       UploadFirmwareFile( mvIMPACT::acquire::GenICam::ODevFileStream& uploadFile, bool boSilentMode, const wxString& serial, const char* pBuf, const size_t bufSize, const wxFileOffset fileOperationBlockSize );
    void                                UserSetBackup( bool boSilentMode );
    void                                UserSetRestore( bool boSilentMode, const wxString& previousUserSetDefaultValueToRestore );
    void                                WaitForDeviceToReappear( const wxString& serial );
public:
    explicit                            DeviceHandlerBlueDevice( mvIMPACT::acquire::Device* pDev );
    static DeviceHandler*               Create( mvIMPACT::acquire::Device* pDev )
    {
        return new DeviceHandlerBlueDevice( pDev );
    }
    virtual bool                        GetIDFromUser( long& newID, const long minValue, const long maxValue );
    virtual int                         GetLatestFirmwareVersion( Version& latestFirmwareVersion ) const;
    virtual int                         GetLatestFirmwarePackageVersion( wxString& latestFirmwarePackageVersion ) const;
    static TUpdateResult                ParsePackageDescriptionFromBuffer( PackageDescriptionFileParser& parser, const char* pPackageDescription, const size_t bufferSize, DeviceConfigureFrame* pParent );
    virtual void                        SetCustomFirmwareFile( const wxString& customFirmwareFile );
    virtual void                        SetCustomFirmwarePath( const wxString& customFirmwarePath );
    virtual void                        SetCustomGenICamFile( const wxString& customGenICamFile )
    {
        GenICamFile_ = customGenICamFile;
    }
    static void                        SetPackageDescriptionBCX( const wxString& packageDescriptionBCX )
    {
        packageDescriptionBCX_ = packageDescriptionBCX;
    }
    static void                        SetPackageDescriptionBF3( const wxString& packageDescriptionBF3 )
    {
        packageDescriptionBF3_ = packageDescriptionBF3;
    }
    virtual bool                        SupportsFirmwareUpdate( void ) const
    {
        return !firmwareUpdateFileName_.IsEmpty();
    }
    virtual bool                        SupportsFirmwareUpdateFromInternet( void ) const
    {
        switch( product_ )
        {
        case pgBlueCOUGAR_X:
        case pgBlueFOX3:
            return true;
        default:
            break;
        }
        return false;
    }
    virtual int                         UpdateFirmware( bool boSilentMode, bool boPersistentUserSets );
};

int                                     CompareFileVersion( const wxString& first, const wxString& second );
wxString                                ExtractVersionNumber( const wxString& s );
bool                                    GetNextNumber( wxString& str, long& number );
int64_type                              MACAddressFromString( const std::string& MAC );

#endif // DeviceHandlerBlueDeviceH
