/****************************************************************************
 *
 * Project:  OpenCPN
 * Purpose:  OpenCPN Toolbar
 * Author:   David Register
 *
 ***************************************************************************
 *   Copyright (C) 2010 by David S. Register                               *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA.         *
 **************************************************************************/


#ifndef _TOOLBAR_H__
#define _TOOLBAR_H__

#include "wx/tbarbase.h"
#include <wx/dynarray.h>
#include "styles.h"
#include <vector>

class ocpnFloatingToolbarDialog;

class ToolbarItemContainer{
public:
    ToolbarItemContainer();
    ~ToolbarItemContainer(){}
    
    ToolbarItemContainer( int toolid, wxBitmap bmpNormal, wxBitmap bmpDisabled,
                            wxItemKind kind, wxString tooltip, wxString label)
    {   m_ID = toolid;
        m_tipString = tooltip;
        m_label = label;
        m_toolKind = kind;
        m_bmpNormal = bmpNormal;
        m_bmpDisabled = bmpDisabled;
        m_bRequired = false;
        m_bPlugin = false;
    }

    ToolbarItemContainer( int toolid, wxBitmap bmpNormal, 
                            wxItemKind kind, wxString tooltip, wxString label)
    {   m_ID = toolid;
        m_tipString = tooltip;
        m_label = label;
        m_toolKind = kind;
        m_bmpNormal = bmpNormal;
        m_bmpDisabled = wxNullBitmap;
        m_bRequired = false;
        m_bPlugin = false;
    }

    
    int m_ID;
    wxString m_tipString;
    wxString m_label;
    wxItemKind m_toolKind;
    bool m_bRequired;
    bool m_bPlugin;

    
    wxBitmap m_bmpNormal;
    wxBitmap m_bmpDisabled;
    wxToolBarToolBase *m_tool;
    
    //  Supplemental SVG icons for plugin tools
    wxString m_NormalIconSVG;
    wxString m_RolloverIconSVG;
    wxString m_ToggledIconSVG;
};

//WX_DECLARE_OBJARRAY(ToolbarItemContainer, ArrayOfToolbarItemContainer);
typedef std::vector<ToolbarItemContainer *> ArrayOfToolbarItemContainer;

//----------------------------------------------------------------------------
// GrabberWindow Definition
//----------------------------------------------------------------------------

class GrabberWin: public wxPanel {
public:
      GrabberWin( wxWindow *parent,  ocpnFloatingToolbarDialog *toolbar, float scale_factor,
                  wxString icon_name, wxPoint position = wxDefaultPosition );
      void OnPaint( wxPaintEvent& event );
      void MouseEvent( wxMouseEvent& event );
      void SetColorScheme( ColorScheme cs );
      wxBitmap &GetBitmap(){ return m_bitmap; }
      
      wxBitmap m_bitmap;
      bool m_bLeftDown;
      bool m_bRightDown;
      ocpnStyle::Style* m_style;
      float m_scale_factor;
      ocpnFloatingToolbarDialog *m_ptoolbar;
      bool m_dragging;
      wxString m_icon_name;

DECLARE_EVENT_TABLE()
};


#define TOOLTIPON_TIMER       10000
#define TOOLTIPOFF_TIMER      10001

enum {
    TOOLBAR_HIDE_TO_GRABBER = 0,
    TOOLBAR_HIDE_TO_FIRST_TOOL,
};

class ToolTipWin;
class ocpnToolBarTool;

// ----------------------------------------------------------------------------
// ocpnToolBarSimple is a generic toolbar implementation in pure wxWidgets
//    Adapted from wxToolBarSimple( deprecated )
// ----------------------------------------------------------------------------

class ocpnToolBarSimple: public wxControl {
public:
      // ctors and dtor
      ocpnToolBarSimple() {
            Init();
      }

      ocpnToolBarSimple( wxWindow *parent, wxWindowID winid, const wxPoint& pos = wxDefaultPosition,
                  const wxSize& size = wxDefaultSize, long style = wxNO_BORDER | wxTB_HORIZONTAL,
                  const wxString& name = wxToolBarNameStr ) : m_one_shot(500)  {
            Init();

            Create( parent, winid, pos, size, style, name );
      }

      bool Create( wxWindow *parent, wxWindowID winid, const wxPoint& pos = wxDefaultPosition,
                  const wxSize& size = wxDefaultSize, long style = wxNO_BORDER | wxTB_HORIZONTAL,
                  const wxString& name = wxToolBarNameStr );

      virtual ~ocpnToolBarSimple();

      virtual void SetToggledBackgroundColour( wxColour c ) {
            m_toggle_bg_color = c;
      }
      ;
      virtual void SetColorScheme( ColorScheme cs );

      // implementation from now on
      // --------------------------

      // event handlers
      void OnPaint( wxPaintEvent& event );
      void OnSize( wxSizeEvent& event );
      void OnMouseEvent( wxMouseEvent& event );
      void OnKillFocus( wxFocusEvent& event );
      void OnToolTipTimerEvent( wxTimerEvent& event );
      void OnToolTipOffTimerEvent( wxTimerEvent& event );

      wxToolBarToolBase *AddTool( int toolid, const wxString& label, const wxBitmap& bitmap,
                  const wxBitmap& bmpDisabled, wxItemKind kind = wxITEM_NORMAL,
                  const wxString& shortHelp = wxEmptyString, const wxString& longHelp =
                              wxEmptyString, wxObject *data = NULL );

      wxToolBarToolBase *AddTool( int toolid, const wxString& label, const wxBitmap& bitmap,
                  const wxString& shortHelp = wxEmptyString, wxItemKind kind = wxITEM_NORMAL ) {
            return AddTool( toolid, label, bitmap, wxNullBitmap, kind, shortHelp );
      }

      wxToolBarToolBase *InsertTool( size_t pos, int id, const wxString& label,
                  const wxBitmap& bitmap, const wxBitmap& bmpDisabled, wxItemKind kind,
                  const wxString& shortHelp, const wxString& longHelp, wxObject *clientData );

      wxToolBarToolBase *InsertTool( size_t pos, wxToolBarToolBase *tool );

      // Only allow toggle if returns true. Call when left button up.
      virtual bool OnLeftClick( int toolid, bool toggleDown );

      // Call when right button down.
      virtual void OnRightClick( int toolid, long x, long y );

      // Called when the mouse cursor enters a tool bitmap.
      // Argument is wxID_ANY if mouse is exiting the toolbar.
      virtual void OnMouseEnter( int toolid );
      virtual void DoPluginToolUp();

      size_t GetToolsCount() const { return m_tools.GetCount(); }
      void SetToolShowCount( int count ){ m_nShowTools = count; }
      int GetToolShowCount(){ return m_nShowTools; }

      int GetNoRowsOrColumns() { return m_currentRowsOrColumns; };
      int GetLineCount() { return m_LineCount; };
      int GetVisibleToolCount();

      void SetToolNormalBitmapEx(wxToolBarToolBase *tool, const wxString & iconname);
      void SetToolNormalBitmapSVG(wxToolBarToolBase *tool, wxString fileSVG);

      void EnableRolloverBitmaps( bool enable ){ m_tbenableRolloverBitmaps = enable; }
      
      // get the control with the given id or return NULL
      virtual wxControl *FindControl( int toolid );

      // add a separator to the toolbar
      virtual wxToolBarToolBase *AddSeparator();
      virtual wxToolBarToolBase *InsertSeparator( size_t pos );

      // remove the tool from the toolbar: the caller is responsible for actually
      // deleting the pointer
      virtual wxToolBarToolBase *RemoveTool( int toolid );

      // delete tool either by index or by position
      virtual bool DeleteToolByPos( size_t pos );
      virtual bool DeleteTool( int toolid );

      // delete all tools
      virtual void ClearTools();

      // must be called after all buttons have been created to finish toolbar
      // initialisation
      virtual bool Realize();

      // tools state
      // -----------

      virtual void EnableTool( int toolid, bool enable );
      virtual void ToggleTool( int toolid, bool toggle );

      virtual void SetToolBitmaps( int toolid, wxBitmap *bmp, wxBitmap *bmpRollover );
      virtual void SetToolBitmapsSVG( int id, wxString fileSVGNormal,
                                      wxString fileSVGRollover,
                                      wxString fileSVGToggled );
      
      void InvalidateBitmaps();

      // set/get tools client data (not for controls)
      virtual wxObject *GetToolClientData( int toolid ) const;
      virtual void SetToolClientData( int toolid, wxObject *clientData );

      // returns tool pos, or wxNOT_FOUND if tool isn't found
      virtual int GetToolPos( int id ) const;

      // return true if the tool is toggled
      virtual bool GetToolState( int toolid ) const;

      virtual bool GetToolEnabled( int toolid ) const;

      virtual void SetToolShortHelp( int toolid, const wxString& helpString );
      virtual wxString GetToolShortHelp( int toolid ) const;
      virtual void SetToolLongHelp( int toolid, const wxString& helpString );
      virtual wxString GetToolLongHelp( int toolid ) const;

      virtual void SetToolTooltipHiViz( int id, bool b_hiviz );

      virtual void SetSizeFactor( float factor){ m_sizefactor = factor; InvalidateBitmaps(); }
      // toolbar geometry
      // ----------------

      // the toolbar can wrap - limit the number of columns or rows it may take
      void SetMaxRowsCols( int rows, int cols ) {
            m_maxRows = rows;
            m_maxCols = cols;
      }
      int GetMaxRows() const {
            return m_maxRows;
      }
      int GetMaxCols() const {
            return m_maxCols;
      }

      // get/set the size of the bitmaps used by the toolbar: should be called
      // before adding any tools to the toolbar
      virtual void SetToolBitmapSize( const wxSize& size ) {
            m_defaultWidth = size.x;
            m_defaultHeight = size.y;
      }
      virtual wxSize GetToolBitmapSize() const {
            return wxSize( m_defaultWidth, m_defaultHeight );
      }

      // the button size in some implementations is bigger than the bitmap size:
      // get the total button size (by default the same as bitmap size)
      virtual wxSize GetToolSize() const {
            return GetToolBitmapSize();
      }

      virtual wxRect GetToolRect( int tool_id );

      // returns a (non separator) tool containing the point (x, y) or NULL if
      // there is no tool at this point (corrdinates are client)
      wxToolBarToolBase *FindToolForPosition( wxCoord x, wxCoord y );

      // find the tool by id
      wxToolBarToolBase *FindById( int toolid ) const;

      // return true if this is a vertical toolbar, otherwise false
      bool IsVertical() const {
            return HasFlag( wxTB_LEFT | wxTB_RIGHT | wxTB_VERTICAL);
      }

      // the list of all our tools
      wxToolBarToolsList m_tools;

      // the maximum number of toolbar rows/columns
      int m_maxRows;
      int m_maxCols;

      // the size of the toolbar bitmaps
      wxCoord m_defaultWidth, m_defaultHeight;

      void HideTooltip();
      void KillTooltip();
      void EnableTooltips() { m_btooltip_show = true; }
      void DisableTooltips() { m_btooltip_show = false; }

protected:
      // common part of all ctors
      void Init();

      // implement base class pure virtuals
      virtual wxToolBarToolBase *DoAddTool( int toolid, const wxString& label,
                  const wxBitmap& bitmap, const wxBitmap& bmpDisabled, wxItemKind kind,
                  const wxString& shortHelp = wxEmptyString, const wxString& longHelp =
                              wxEmptyString, wxObject *clientData = NULL, wxCoord xPos =
                              wxDefaultCoord, wxCoord yPos = wxDefaultCoord );

      virtual bool DoInsertTool( size_t pos, wxToolBarToolBase *tool );
      virtual bool DoDeleteTool( size_t pos, wxToolBarToolBase *tool );

      virtual void DoEnableTool( wxToolBarToolBase *tool, bool enable );
      virtual void DoToggleTool( wxToolBarToolBase *tool, bool toggle );

      virtual wxToolBarToolBase *CreateTool( int winid, const wxString& label,
                  const wxBitmap& bmpNormal, const wxBitmap& bmpDisabled, wxItemKind kind,
                  wxObject *clientData, const wxString& shortHelp, const wxString& longHelp );

      // helpers
      void DrawTool( wxToolBarToolBase *tool );
      virtual void DrawTool( wxDC& dc, wxToolBarToolBase *tool );
      virtual void SpringUpButton( int index );

      int m_currentRowsOrColumns;
      int m_LineCount;

      int m_pressedTool, m_currentTool;

      wxCoord m_lastX, m_lastY;
      wxCoord m_maxWidth, m_maxHeight;
      wxCoord m_xPos, m_yPos;

      wxColour m_toggle_bg_color;
      wxColour m_toolOutlineColour;
      ToolTipWin *m_pToolTipWin;
      ocpnToolBarTool *m_last_ro_tool;

      ColorScheme m_currentColorScheme;

      wxTimer m_tooltip_timer;
      int m_one_shot;
      wxTimer m_tooltipoff_timer;
      int m_tooltip_off;
      bool m_btooltip_show;

      bool m_btoolbar_is_zooming;

      ocpnStyle::Style* m_style;

      float m_sizefactor;

      int m_last_plugin_down_id;
      bool m_leftDown;
      int m_nShowTools;
      bool m_tbenableRolloverBitmaps;

private:
DECLARE_EVENT_TABLE()
};

//----------------------------------------------------------------------------------------------------------
//    ocpnFloatingToolbarDialog Specification
//----------------------------------------------------------------------------------------------------------

#define FADE_TIMER 2
#define DESTROY_TIMER 3

class ocpnFloatingToolbarDialog: public wxFrame {
DECLARE_EVENT_TABLE()

public:
      ocpnFloatingToolbarDialog( wxWindow *parent, wxPoint position, long orient, float size_factor );
      ~ocpnFloatingToolbarDialog();

      void OnClose( wxCloseEvent& event );
      void OnWindowCreate( wxWindowCreateEvent& event );
      void OnToolLeftClick( wxCommandEvent& event );
      virtual void OnKeyDown( wxKeyEvent &event );
      virtual void OnKeyUp( wxKeyEvent &event );
      void MouseEvent( wxMouseEvent& event );
      void FadeTimerEvent( wxTimerEvent& event );
      bool IsToolbarShown() { return ( m_ptoolbar != 0 ); }
      float GetScaleFactor() { return m_sizefactor; }
      void SetGrabber( wxString icon_name );
      void DestroyTimerEvent( wxTimerEvent& event );
      
      void EnableSubmerge(bool enable){ m_benableSubmerge = enable; }
      void Realize();
      ocpnToolBarSimple *GetToolbar();
      ocpnToolBarSimple *CreateNewToolbar();
      void SetToolbarHideMethod(int n_method ){ n_toolbarHideMethod = n_method; }
      
      void SetToolConfigString(wxString string){ m_configString = string; }
      wxString GetToolConfigString(){ return m_configString; }

      float GetSizeFactor(){ return m_sizefactor; }
      
      void CreateConfigMenu();
      bool _toolbarConfigMenuUtil( ToolbarItemContainer *tic );

      void SetCornerRadius( int radius){ m_cornerRadius = radius; }
      
      void SetGrabberEnable( bool bShow ){ m_bGrabberEnable = bShow; }
      void Submerge();
      void SubmergeToGrabber();
      bool isSubmergedToGrabber();
      void Surface();
      void SurfaceFromGrabber();
      void HideTooltip();
      void ShowTooltips();
      void EnableTooltips() { if(m_ptoolbar) m_ptoolbar->EnableTooltips(); }
      void DisableTooltips() { if(m_ptoolbar) m_ptoolbar->DisableTooltips(); }
      void UpdateRecoveryWindow(bool b_toolbarEnable);
      void EnableTool( int toolid, bool enable );
      void SetToolShortHelp( int toolid, const wxString& helpString );
      
      void DestroyToolBar();
      void ToggleOrientation();
      void MoveDialogInScreenCoords( wxPoint posn, wxPoint posn_old );
      void RePosition();
      void LockPosition(bool lock){ m_block = lock; }
      virtual void SetColorScheme( ColorScheme cs );
      ColorScheme GetColorScheme(){ return m_cs; }
      bool CheckSurfaceRequest( wxMouseEvent &event );
      
      void SetGeometry(bool bAvoid, wxRect rectAvoid);
      void SetMinX( int offset ){ m_dock_min_x = offset; }
      void SetMinY( int offset ){ m_dock_min_y = offset; }
      long GetOrient() { return m_orient; }
      wxSize GetToolSize();

      void RefreshFadeTimer();
      void SetAutoHideTimer(int time);
      void SetAutoHide( bool hide ){ m_bAutoHideToolbar = hide; }
      
      size_t GetToolCount();
      void SetToolShowMask( wxString mask );
      wxString GetToolShowMask( void ){ return m_toolShowMask; }
      
      void SetToolShowCount( int count );
      int GetToolShowCount( void );
      
      bool CheckAndAddPlugInTool( ocpnToolBarSimple *tb );
      bool AddDefaultPositionPlugInTools( ocpnToolBarSimple *tb );
      ocpnToolBarSimple *CreateMyToolbar();
      
      int GetDockX() { return m_dock_x; }
      int GetDockY() { return m_dock_y; }
      void SetDockX( int x) { m_dock_x = x; }
      void SetDockY( int y) { m_dock_y = y; }
      
      void SetYAuxOffset( int offset ){ m_auxOffsetY = offset; }
      
      void SetCanToggleOrientation(bool enable){ b_canToggleOrientation = enable; }
      bool GetCanToggleOrientation(){ return b_canToggleOrientation; }
      
      bool toolbarConfigChanged;
      GrabberWin *m_pRecoverwin;
      bool m_bnavgrabber;
      
      wxMenu  *m_FloatingToolbarConfigMenu;

      wxString m_tblastAISiconName;
      wxToolBarToolBase *m_pTBAISTool;
      bool m_toolbar_scale_tools_shown;
      void SetBackGroundColorString( wxString colorRef );
      void SetULDockPosition(wxPoint position);
      
      ArrayOfToolbarItemContainer m_Items;
      
      void AddToolItem(ToolbarItemContainer *item);
      int RebuildToolbar();
      void EnableRolloverBitmaps( bool bEnable );
      bool GetEnableRolloverBitmaps(){ return m_enableRolloverBitmaps; }
      
protected:
    ocpnToolBarSimple *m_ptoolbar;
    
private:
      void DoFade( int value );

      bool  m_bsubmerged;
      bool  m_bsubmergedToGrabber;
      
      wxWindow *m_pparent;
      wxBoxSizer *m_topSizer;

      GrabberWin *m_pGrabberwin;

      long m_orient;
      wxTimer m_fade_timer;
      int m_opacity;
      ColorScheme m_cs;

      wxPoint m_position;
      int m_dock_x;
      int m_dock_y;
      int m_dock_min_x;
      int m_dock_min_y;
      
      ocpnStyle::Style* m_style;
      bool m_block;

      bool m_marginsInvisible;
      float m_sizefactor;
      wxTimer m_destroyTimer;
      GrabberWin *m_destroyGrabber;
      wxSize m_recoversize;
      
      bool m_bAutoHideToolbar;
      int m_nAutoHideToolbar;
      bool m_benableSubmerge;
      bool m_bGrabberEnable;
      
      wxString m_backcolorString;
      int m_cornerRadius;
      wxString m_toolShowMask;
      int n_toolbarHideMethod;
      bool b_canToggleOrientation;
      wxString m_configString;
      bool m_enableRolloverBitmaps;
      int m_auxOffsetY;
};

//---------------------------------------------------------------------------

class ToolbarMOBDialog : public wxDialog{
private:
    std::vector<wxRadioButton*> choices;

public:
    ToolbarMOBDialog( wxWindow* parent );
    int GetSelection();
};


#define SYMBOL_ToolbarChoices_STYLE wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX

class ToolbarChoicesDialog: public wxDialog
{
    DECLARE_DYNAMIC_CLASS( ToolbarChoicesDialog )
    DECLARE_EVENT_TABLE()
    
public:
    /// Constructors
    ToolbarChoicesDialog( );
    ToolbarChoicesDialog( wxWindow* parent, wxWindow *sponsor, wxWindowID id = -1,
                        const wxString& caption = _T(""),
                          const wxPoint& pos = wxDefaultPosition,
                          const wxSize& size = wxDefaultSize,
                          long style = SYMBOL_ToolbarChoices_STYLE );
    
    ~ToolbarChoicesDialog();
    
    void SetColorScheme(ColorScheme cs);
    void RecalculateSize( void );
    void CreateControls();
    
    void OnCancelClick( wxCommandEvent& event );
    void OnOkClick( wxCommandEvent& event );
    
    
    wxButton*     m_CancelButton;
    wxButton*     m_OKButton;

    std::vector<wxCheckBox*> cboxes;
    wxMenu        *m_configMenu;
    ocpnFloatingToolbarDialog *m_ToolbarDialogAncestor;
};

#endif
