/// QasTools: Desktop toolset for the Linux sound system ALSA.
/// \copyright See COPYING file.

#include "mixers_view.hpp"
#include "mwdg/event_types.hpp"
#include "mwdg/mixers_delegate.hpp"
#include <QCoreApplication>
#include <QScrollBar>
#include <iostream>

namespace MWdg
{

Mixers_View::Mixers_View ( QWidget * parent_n )
: QListView ( parent_n )
{
  setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff );
  {
    QSizePolicy policy ( sizePolicy () );
    policy.setVerticalPolicy ( QSizePolicy::Expanding );
    setSizePolicy ( policy );
  }

  setSelectionMode ( QAbstractItemView::SingleSelection );
  setItemDelegate ( new MWdg::Mixers_Delegate ( this ) );
}

Mixers_View::~Mixers_View () = default;

QSize
Mixers_View::minimumSizeHint () const
{
  ensurePolished ();

  QSize res;
  int & ww = res.rwidth ();
  int & hh = res.rheight ();

  QSize vsb_msh = verticalScrollBar ()->minimumSizeHint ();
  QSize vsb_sh = verticalScrollBar ()->sizeHint ();

  // Width
  {
    // Content width approximation
    ww = fontMetrics ().averageCharWidth () * _chars_vis_min;
    ww = qMax ( 16, ww );
    // Add spacing
    if ( spacing () > 0 ) {
      ww += spacing () * 2;
    }
    // Add scrollbar width
    if ( vsb_msh.width () > 0 ) {
      ww += vsb_msh.width ();
    } else if ( vsb_sh.width () > 0 ) {
      ww += vsb_sh.width ();
    }
    // Add frame width
    ww += frameWidth () * 2;
  }

  // Height
  {
    int row_height = fontMetrics ().height ();
    if ( spacing () > 0 ) {
      row_height += spacing () * 2;
    }
    hh = qMax ( vsb_msh.height (), row_height );
    // Add frame width
    hh += frameWidth () * 2;
  }
  {
    QMargins mg = contentsMargins ();
    ww += mg.left () + mg.right ();
    hh += mg.top () + mg.bottom ();
  }
  return res;
}

QSize
Mixers_View::sizeHint () const
{
  ensurePolished ();

  QSize res;
  int & ww ( res.rwidth () );
  int & hh ( res.rheight () );

  QSize vsb_sh = verticalScrollBar ()->sizeHint ();

  // Width
  {
    ww = fontMetrics ().averageCharWidth () * _chars_vis_avrg;
    if ( spacing () > 0 ) {
      ww += spacing () * 2;
    }
    if ( vsb_sh.width () > 0 ) {
      ww += vsb_sh.width ();
    }
    // Add frame width
    ww += frameWidth () * 2;
  }

  // Height
  {
    int rh_row ( fontMetrics ().height () * 3 / 2 );
    if ( spacing () > 0 ) {
      rh_row += spacing () * 2;
    }
    hh = rh_row * _show_rows_avrg;
    hh = qMax ( vsb_sh.height (), hh );
    // Add frame width
    hh += frameWidth () * 2;
  }
  {
    QMargins mg = contentsMargins ();
    ww += mg.left () + mg.right ();
    hh += mg.top () + mg.bottom ();
  }
  return res;
}

void
Mixers_View::setModel ( QAbstractItemModel * model_n )
{
  if ( model () != nullptr ) {
    disconnect ( model (), 0, this, 0 );
  }

  QListView::setModel ( model_n );

  if ( model () != nullptr ) {
    connect ( model (),
              SIGNAL ( modelReset () ),
              this,
              SLOT ( maximum_height_update_request () ) );

    connect ( model (),
              SIGNAL ( layoutChanged () ),
              this,
              SLOT ( maximum_height_update_request () ) );

    connect ( model (),
              SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ),
              this,
              SLOT ( maximum_height_update_request () ) );

    connect ( model (),
              SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ),
              this,
              SLOT ( maximum_height_update_request () ) );
  }
  maximum_height_update_request ();
}

void
Mixers_View::maximum_height_update_request ()
{
  if ( !_maximum_update_requested ) {
    _maximum_update_requested = true;
    QCoreApplication::postEvent ( this, new QEvent ( MWdg::evt_refresh_data ) );
  }
}

bool
Mixers_View::event ( QEvent * event_n )
{
  bool res ( false );
  if ( event_n->type () == MWdg::evt_refresh_data ) {
    _maximum_update_requested = false;
    maximum_height_update ();
    res = true;
  } else {
    res = QListView::event ( event_n );
  }
  return res;
}

void
Mixers_View::changeEvent ( QEvent * event_n )
{
  maximum_height_update_request ();
  QListView::changeEvent ( event_n );
}

void
Mixers_View::maximum_height_update ()
{
  int hsum = 16000;
  int vspace = 0;
  if ( spacing () > 0 ) {
    vspace = spacing () * 2;
  }
  if ( model () != nullptr ) {
    hsum = 0;
    hsum += frameWidth () * 2;
    for ( int ii = 0; ii < model ()->rowCount (); ++ii ) {
      int hrow ( qMax ( sizeHintForRow ( ii ), 0 ) );
      hrow += vspace;
      hsum += hrow;
    }
  }
  // std::cout << "Mixers_View::maximum_height_update " << hsum << "\n";

  if ( maximumHeight () != hsum ) {
    setMaximumHeight ( hsum );
  }
}

} // namespace MWdg
