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

#pragma once

namespace Wdg
{

/// @return The distance between the values as unsigned int
///
unsigned int
integer_distance ( int int_min_n, int int_max_n );

unsigned long
integer_distance ( long int_min_n, long int_max_n );

unsigned int
permille ( unsigned long current_n, unsigned long total_n );

/// @brief ulong to ulong span mapper interface definition class
///
class UInt_Mapper
{
  public:
  // -- Construction

  UInt_Mapper ();

  virtual ~UInt_Mapper ();

  // -- Mapping

  virtual unsigned long
  map ( unsigned long val_n ) const = 0;
};

/// @brief Maps down to a coarser range
///
class UInt_Mapper_Down : public UInt_Mapper
{
  public:
  // -- Construction

  ///
  /// @param max_idx_fine The maximum index of the fine ladder (num_steps - 1).
  /// @param max_idx_coarse The maximum index of the coarse ladder (num_steps -
  /// 1).
  UInt_Mapper_Down ( unsigned long max_idx_fine = 1,
                     unsigned long max_idx_coarse = 1 );

  ~UInt_Mapper_Down () override;

  // -- Mapping

  unsigned long
  map ( unsigned long val_n ) const override;

  private:
  // -- Attributes
  unsigned long _max_idx_fine;
  unsigned long _max_idx_coarse;
  unsigned long _dist_small;
  unsigned long _dist_large;
  unsigned long _len_mod;
  unsigned long _mid_pos;
};

/// @brief Maps up to a finer range
///
class UInt_Mapper_Up : public UInt_Mapper
{
  public:
  // -- Construction

  ///
  /// @param max_idx_coarse Maximum index of the coarse ladder (num_steps - 1).
  /// @param max_idx_fine Maximum index of the fine ladder (num_steps - 1).
  UInt_Mapper_Up ( unsigned long max_idx_coarse = 1,
                   unsigned long max_idx_fine = 1 );

  ~UInt_Mapper_Up () override;

  // -- Mapping

  unsigned long
  map ( unsigned long val_n ) const;

  unsigned long
  min_dist () const
  {
    return _len_div;
  }

  private:
  // -- Attributes
  unsigned long _max_idx_coarse;
  unsigned long _max_idx_fine;
  unsigned long _len_div;
  unsigned long _len_mod;
};

/// @brief Maps between two ranges in both directions
///
class UInt_Mapper_Auto
{
  public:
  // -- Construction

  UInt_Mapper_Auto ( unsigned long max_idx_1_n = 0,
                     unsigned long max_idx_2_n = 0 );

  ~UInt_Mapper_Auto ();

  // -- Setup

  unsigned long
  max_idx_1 () const
  {
    return _max_idx_1;
  }

  unsigned long
  max_idx_2 () const
  {
    return _max_idx_2;
  }

  void
  set_max_idx_all ( unsigned long max_idx_1_n, unsigned long max_idx_2_n );

  // -- Mapping

  unsigned long
  v1_to_v2 ( unsigned long val_n ) const;

  unsigned long
  v2_to_v1 ( unsigned long val_n ) const;

  private:
  // -- Attributes
  unsigned long _max_idx_1;
  unsigned long _max_idx_2;
  UInt_Mapper_Up _mapper_up;
  UInt_Mapper_Down _mapper_down;
};

} // namespace Wdg
