//+----------------------------------------------------------------------------+
//| Description:  Magic Set Editor - Program to make Magic (tm) cards          |
//| Copyright:    (C) Twan van Laarhoven and the other MSE developers          |
//| License:      GNU General Public License 2 or later (see file COPYING)     |
//+----------------------------------------------------------------------------+

#pragma once

// ----------------------------------------------------------------------------- : Includes

#include <util/prec.hpp>
#include <wx/listctrl.h>

// ----------------------------------------------------------------------------- : ItemList

/// A generic list of items
/** The list is shown in report mode, and allows sorting.
 *  Currently used for cards and keywords.
 *
 *  Terminology:
 *     selected item = a single item in the variable selected_item
 *     focused items = items that are drawn as selected in the control
 *  TODO: This is reverse of normal
 */
class ItemList : public wxListView {
public:
  ItemList(Window* parent, int id, long additional_style = 0, bool multi_sel = false);
  
  // --------------------------------------------------- : Selection
  
  /// Is there a previous item to select?
  bool canSelectPrevious() const;
  /// Is there a next item to select?
  bool canSelectNext() const;
  /// Can we select all?
  bool canSelectAll() const;
  /// Move the selection to the previous item (if possible)
  void selectPrevious();
  /// Move the selection to the next item (if possible)
  void selectNext();
  /// Move the selection to the first item (if possible)
  void selectFirst();
  /// Select all items
  void doSelectAll();
  
  // --------------------------------------------------- : Clipboard
  
  virtual bool canCut()    const { return canCopy() && canDelete(); }
  virtual bool canCopy()   const { return false; }
  virtual bool canPaste()  const { return false; }
  virtual bool canDelete() const { return false; }
  // Try to perform a clipboard operation, return success
  virtual bool doCut();
  virtual bool doCopy()   { return false; }
  virtual bool doPaste()  { return false; }
  virtual bool doDelete() { return false; }
  
  // --------------------------------------------------- : Virtual interface
protected:
  /// Get a list of all items
  virtual void getItems(vector<VoidP>& out) const = 0;
  
  /// Send an 'item selected' event for the currently selected item (selected_item)
  virtual void sendEvent() = 0;
  
  /// Is sorting required?
  virtual bool mustSort() const { return false; }
  /// Compare two items for < based on sort_by_column (not on sort_ascending)
  virtual bool compareItems(void* a, void* b) const = 0;
  
  // --------------------------------------------------- : Protected interface
  /// Return the card at the given position in the sorted list
  inline const VoidP& getItem(long pos) const { return sorted_list[pos]; }
  /// Sort by the given column
  virtual void sortBy(long column, bool ascending);
  /// Refresh the card list (resort, refresh and reselect current item)
  void refreshList(bool refresh_current_only = false);
  /// Set the image of a column header (fixes wx bug)
  void SetColumnImage(int col, int image);
  
  /// Select an item, send an event to the parent
  /** If focus then the item is also focused and selected in the actual control.
   *  This should not be done when the item is selected because it was focused (leading to a loop).
   */
  void selectItem(const VoidP& item, bool focus, bool event);
  /// Select a item at the specified position
  void selectItemPos(long pos, bool focus, bool force_focus = false);
  /// Find the position for the selected_item
  void findSelectedItemPos();
  /// Actually select the item at selected_item_pos in the control
  /** if force_focus == true, then the item is highlighted again if it already is focused. */
  void focusSelectedItem(bool force_focus = false);
  /// Deselect everything in the control
  void focusNone();
  /// Actually select a certain item in the control
  void focusItem(const VoidP& item, bool focus = true);
  /// Count the number of focused items
  long focusCount() const;

  // --------------------------------------------------- : Fixing wx issues

  wxSize DoGetBestClientSize() const override;

  // --------------------------------------------------- : Data
  VoidP          selected_item;     ///< The currently selected item
  long           selected_item_pos; ///< Position of the selected item in the sorted_list, or -1 if no card is selected
  long           sort_by_column;    ///< Column to use for sorting, or -1 if not sorted
  bool           sort_ascending;    ///< Sort order
  vector<VoidP>  sorted_list;       ///< Sorted list of items, can be considered a map: pos->item
  
private:
  struct ItemComparer; // for comparing items
  
  // --------------------------------------------------- : Window events
  DECLARE_EVENT_TABLE();
  
  void onColumnClick(wxListEvent& ev);
  void onItemFocus  (wxListEvent& ev);
  void onContextMenu(wxContextMenuEvent&);
};

