#ifndef __AUDACITY_MEMORY_X_H__
#define __AUDACITY_MEMORY_X_H__

// C++ standard header <memory> with a few extensions
#include <memory>
#include <cstdlib> // Needed for free.
#ifndef safenew
#define safenew new
#endif


#include <functional>

#if !(_MSC_VER >= 1800 || __cplusplus >= 201402L)
/* replicate the very useful C++14 make_unique for those build environments
that don't implement it yet.
typical useage:
auto p = std::make_unique<Myclass>(ctorArg1, ctorArg2, ... ctorArgN);
p->DoSomething();
auto q = std::make_unique<Myclass[]>(count);
q[0].DoSomethingElse();

The first hides naked NEW and DELETE from the source code.
The second hides NEW[] and DELETE[].  Both of course ensure destruction if
you don't use something like std::move(p) or q.release().  Both expressions require
that you identify the type only once, which is brief and less error prone.

(Whereas this omission of [] might invite a runtime error:
std::unique_ptr<Myclass> q { safenew Myclass[count] }; )

Some C++11 tricks needed here are (1) variadic argument lists and
(2) making the compile-time dispatch work correctly.  You can't have
a partially specialized template function, but you get the effect of that
by other metaprogramming means.
*/

namespace std {
   // For overloading resolution
   template <typename X> struct __make_unique_result {
      using scalar_case = unique_ptr<X>;
   };

   // Partial specialization of the struct for array case
   template <typename X> struct __make_unique_result<X[]> {
      using array_case = unique_ptr<X[]>;
      using element = X;
   };

   // Now the scalar version of unique_ptr
   template<typename X, typename... Args> inline
      typename __make_unique_result<X>::scalar_case
      make_unique(Args&&... args)
   {
      return typename __make_unique_result<X>::scalar_case
      { safenew X(forward<Args>(args)...) };
   }

   // Now the array version of unique_ptr
   // The compile-time dispatch trick is that the non-existence
   // of the scalar_case type makes the above overload
   // unavailable when the template parameter is explicit
   template<typename X> inline
      typename __make_unique_result<X>::array_case
      make_unique(size_t count)
   {
      return typename __make_unique_result<X>::array_case
      { safenew typename __make_unique_result<X>::element[count] };
   }
}
#endif

/*
 * ArrayOf<X>
 * Not to be confused with std::array (which takes a fixed size) or std::vector
 * This maintains a pointer allocated by NEW X[].  It's cheap: only one pointer,
 * with no size and capacity information for resizing as for vector, and if X is
 * a built-in numeric or pointer type, by default there is no zero filling at
 * allocation time.
 */

template<typename X>
class ArrayOf : public std::unique_ptr<X[]>
{
public:
   ArrayOf() {}

   template<typename Integral>
   explicit ArrayOf(Integral count, bool initialize = false)
   {
      static_assert(std::is_unsigned<Integral>::value, "Unsigned arguments only");
      reinit(count, initialize);
   }

   //ArrayOf(const ArrayOf&) PROHIBITED;
   ArrayOf(const ArrayOf&) = delete;
   ArrayOf(ArrayOf&& that)
      : std::unique_ptr < X[] >
         (std::move((std::unique_ptr < X[] >&)(that)))
   {
   }
   ArrayOf& operator= (ArrayOf &&that)
   {
      std::unique_ptr<X[]>::operator=(std::move(that));
      return *this;
   }
   ArrayOf& operator= (std::unique_ptr<X[]> &&that)
   {
      std::unique_ptr<X[]>::operator=(std::move(that));
      return *this;
   }

   template< typename Integral >
   void reinit(Integral count,
               bool initialize = false)
   {
      static_assert(std::is_unsigned<Integral>::value, "Unsigned arguments only");
      if (initialize)
         // Initialize elements (usually, to zero for a numerical type)
         std::unique_ptr<X[]>::reset(safenew X[count]{});
      else
         // Avoid the slight initialization overhead
         std::unique_ptr<X[]>::reset(safenew X[count]);
   }
};

/**
  \class ArrayOf

  ArraysOf<X>

  \brief This simplifies arrays of arrays, each array separately allocated with NEW[]
  But it might be better to use std::Array<ArrayOf<X>, N> for some small constant N
  Or use just one array when sub-arrays have a common size and are not large.
 */
template<typename X>
class ArraysOf : public ArrayOf<ArrayOf<X>>
{
public:
   ArraysOf() {}

   template<typename Integral>
   explicit ArraysOf(Integral N)
      : ArrayOf<ArrayOf<X>>( N )
   {}

   template<typename Integral1, typename Integral2 >
   ArraysOf(Integral1 N, Integral2 M, bool initialize = false)
   : ArrayOf<ArrayOf<X>>( N )
   {
      static_assert(std::is_unsigned<Integral1>::value, "Unsigned arguments only");
      static_assert(std::is_unsigned<Integral2>::value, "Unsigned arguments only");
      for (size_t ii = 0; ii < N; ++ii)
         (*this)[ii] = ArrayOf<X>{ M, initialize };
   }

   //ArraysOf(const ArraysOf&) PROHIBITED;
   ArraysOf(const ArraysOf&) =delete;
   ArraysOf& operator= (ArraysOf&& that)
   {
      ArrayOf<ArrayOf<X>>::operator=(std::move(that));
      return *this;
   }

   template< typename Integral >
   void reinit(Integral count)
   {
      ArrayOf<ArrayOf<X>>::reinit( count );
   }

   template< typename Integral >
   void reinit(Integral count, bool initialize)
   {
      ArrayOf<ArrayOf<X>>::reinit( count, initialize );
   }

   template<typename Integral1, typename Integral2 >
   void reinit(Integral1 countN, Integral2 countM, bool initialize = false)
   {
      static_assert(std::is_unsigned<Integral1>::value, "Unsigned arguments only");
      static_assert(std::is_unsigned<Integral2>::value, "Unsigned arguments only");
      reinit(countN, false);
      for (size_t ii = 0; ii < countN; ++ii)
         (*this)[ii].reinit(countM, initialize);
   }
};

/**
  \class Optional
  \brief Like a smart pointer, allows for object to not exist (nullptr)
  \brief emulating some of std::optional of C++17

  template class Optional<X>
  Can be used for monomorphic objects that are stack-allocable, but only conditionally constructed.
  You might also use it as a member.
  Initialize with emplace(), then use like a smart pointer,
  with *, ->, reset(), or in if()
 */

// Placement-NEW is used below, and that does not cooperate with the DEBUG_NEW for Visual Studio
#ifdef _DEBUG
#ifdef _MSC_VER
#undef new
#endif
#endif


template<typename X>
class Optional {
public:

   using value_type = X;

   // Construct as NULL
   Optional() {}

   // Supply the copy and move, so you might use this as a class member too
   Optional(const Optional &that)
   {
      if (that)
         emplace(*that);
   }

   Optional& operator= (const Optional &that)
   {
      if (this != &that) {
         if (that)
            emplace(*that);
         else
            reset();
      }
      return *this;
   }

   Optional(Optional &&that)
   {
      if (that)
         emplace(::std::move(*that));
   }

   Optional& operator= (Optional &&that)
   {
      if (this != &that) {
         if (that)
            emplace(::std::move(*that));
         else
            reset();
      }
      return *this;
   }

   /// Make an object in the buffer, passing constructor arguments,
   /// but destroying any previous object first
   /// Note that if constructor throws, we remain in a consistent
   /// NULL state -- giving exception safety but only weakly
   /// (previous value was lost if present)
   template<typename... Args>
   X& emplace(Args&&... args)
   {
      // Lose any old value
      reset();
      // emplace NEW value
      pp = safenew(address()) X(std::forward<Args>(args)...);
      return **this;
   }

   // Destroy any object that was built in it
   ~Optional()
   {
      reset();
   }

   // Pointer-like operators

   /// Dereference, with the usual bad consequences if NULL
   X &operator* () const
   {
      return *pp;
   }

   X *operator-> () const
   {
      return pp;
   }

   void reset()
   {
      if (pp)
         pp->~X(), pp = nullptr;
   }

   // So you can say if(ptr)
   explicit operator bool() const
   {
      return pp != nullptr;
   }

   bool has_value() const
   {
      return pp != nullptr;
   }

private:
   X* address()
   {
      return reinterpret_cast<X*>(&storage);
   }

   // Data
#if 0
   typename ::std::aligned_storage<
      sizeof(X)
      // , alignof(X) // Not here yet in all compilers
   >::type storage{};
#else
   union {
      double d;
      char storage[sizeof(X)];
   };
#endif
   X* pp{ nullptr };
};

// Restore definition of debug new
#ifdef _DEBUG
#ifdef _MSC_VER
#undef THIS_FILE
static const char THIS_FILE[] = __FILE__;
#define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__)
#endif
#endif

/**
  A deleter for pointers obtained with malloc
 */
struct freer { void operator() (void *p) const { free(p); } };

/**
  A useful alias for holding the result of malloc
 */
template< typename T >
using MallocPtr = std::unique_ptr< T, freer >;

/**
  A useful alias for holding the result of strup and similar
 */
template <typename Character = char>
using MallocString = std::unique_ptr< Character[], freer >;

/**
  \brief A deleter class to supply the second template parameter of unique_ptr for
  classes like wxWindow that should be sent a message called Destroy rather
  than be deleted directly
 */
template <typename T>
struct Destroyer {
   void operator () (T *p) const { if (p) p->Destroy(); }
};

/**
  \brief a convenience for using Destroyer
 */
template <typename T>
using Destroy_ptr = std::unique_ptr<T, Destroyer<T>>;

/**
  \brief "finally" as in The C++ Programming Language, 4th ed., p. 358
  Useful for defining ad-hoc RAII actions.
  typical usage:
  auto cleanup = finally([&]{ ... code; ... });
 */

// Construct this from any copyable function object, such as a lambda
template <typename F>
struct Final_action {
   Final_action(F f) : clean( f ) {}
   ~Final_action() { clean(); }
   F clean;
};

/// \brief Function template with type deduction lets you construct Final_action
/// without typing any angle brackets
template <typename F>
Final_action<F> finally (F f)
{
   return Final_action<F>(f);
}

#include <wx/utils.h> // for wxMin, wxMax
#include <algorithm>

/**
  \brief Structure used by ValueRestorer 
 */
template< typename T >
struct RestoreValue {
   T oldValue;
   void operator () ( T *p ) const { if (p) *p = oldValue; }
};


/**
  \brief Set a variable temporarily in a scope
  */
template< typename T >
class ValueRestorer : public std::unique_ptr< T, RestoreValue<T> >
{
   using std::unique_ptr< T, RestoreValue<T> >::reset; // make private
   // But release() remains public and can be useful to commit a changed value
public:
   explicit ValueRestorer( T &var )
      : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
   {}
   explicit ValueRestorer( T &var, const T& newValue )
      : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
   { var = newValue; }
   ValueRestorer(ValueRestorer &&that)
      : std::unique_ptr < T, RestoreValue<T> > ( std::move(that) ) {};
   ValueRestorer & operator= (ValueRestorer &&that)
   {
      if (this != &that)
         std::unique_ptr < T, RestoreValue<T> >::operator=(std::move(that));
      return *this;
   }
};

/// inline functions provide convenient parameter type deduction
template< typename T >
ValueRestorer< T > valueRestorer( T& var )
{ return ValueRestorer< T >{ var }; }

template< typename T >
ValueRestorer< T > valueRestorer( T& var, const T& newValue )
{ return ValueRestorer< T >{ var, newValue }; }

/**
  \brief A convenience for defining iterators that return rvalue types, so that
  they cooperate correctly with stl algorithms and std::reverse_iterator
 */
template< typename Value, typename Category = std::forward_iterator_tag >
using ValueIterator = std::iterator<
   Category, const Value, ptrdiff_t,
   // void pointer type so that operator -> is disabled
   void,
   // make "reference type" really the same as the value type
   const Value
>;

/**
  \brief A convenience for use with range-for
 */
template <typename Iterator>
struct IteratorRange : public std::pair<Iterator, Iterator> {
   using iterator = Iterator;
   using reverse_iterator = std::reverse_iterator<Iterator>;

   IteratorRange (const Iterator &a, const Iterator &b)
   : std::pair<Iterator, Iterator> ( a, b ) {}

   IteratorRange (Iterator &&a, Iterator &&b)
   : std::pair<Iterator, Iterator> ( std::move(a), std::move(b) ) {}

   IteratorRange< reverse_iterator > reversal () const
   { return { this->rbegin(), this->rend() }; }

   Iterator begin() const { return this->first; }
   Iterator end() const { return this->second; }

   reverse_iterator rbegin() const { return reverse_iterator{ this->second }; }
   reverse_iterator rend() const { return reverse_iterator{ this->first }; }

   bool empty() const { return this->begin() == this->end(); }
   explicit operator bool () const { return !this->empty(); }
   size_t size() const { return std::distance(this->begin(), this->end()); }

   template <typename T> iterator find(const T &t) const
   { return std::find(this->begin(), this->end(), t); }

   template <typename T> long index(const T &t) const
   {
      auto iter = this->find(t);
      if (iter == this->end())
         return -1;
      return std::distance(this->begin(), iter);
   }

   template <typename T> bool contains(const T &t) const
   { return this->end() != this->find(t); }

   template <typename F> iterator find_if(const F &f) const
   { return std::find_if(this->begin(), this->end(), f); }

   template <typename F> long index_if(const F &f) const
   {
      auto iter = this->find_if(f);
      if (iter == this->end())
         return -1;
      return std::distance(this->begin(), iter);
   }

   // to do: use std::all_of, any_of, none_of when available on all platforms
   template <typename F> bool all_of(const F &f) const
   {
      auto notF =
         [&](typename std::iterator_traits<Iterator>::reference v)
            { return !f(v); };
      return !this->any_of( notF );
   }

   template <typename F> bool any_of(const F &f) const
   { return this->end() != this->find_if(f); }

   template <typename F> bool none_of(const F &f) const
   { return !this->any_of(f); }

   template<typename T> struct identity
      { const T&& operator () (T &&v) const { return std::forward(v); } };

   // Like std::accumulate, but the iterators implied, and with another
   // unary operation on the iterator value, pre-composed
   template<
      typename R,
      typename Binary = std::plus< R >,
      typename Unary = identity< decltype( *std::declval<Iterator>() ) >
   >
   R accumulate(
      R init,
      Binary binary_op = {},
      Unary unary_op = {}
   ) const
   {
      R result = init;
      for (auto&& v : *this)
         result = binary_op(result, unary_op(v));
      return result;
   }

   // An overload making it more convenient to use with pointers to member
   // functions
   template<
      typename R,
      typename Binary = std::plus< R >,
      typename R2, typename C
   >
   R accumulate(
      R init,
      Binary binary_op,
      R2 (C :: * pmf) () const
   ) const
   {
      return this->accumulate( init, binary_op, std::mem_fn( pmf ) );
   }

   // Some accumulations frequent enough to be worth abbreviation:
   template<
      typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
      typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
   >
   R min( Unary unary_op = {} ) const
   {
      return this->accumulate(
         std::numeric_limits< R >::max(),
         (const R&(*)(const R&, const R&)) std::min,
         unary_op
      );
   }

   template<
      typename R2, typename C,
      typename R = R2
   >
   R min( R2 (C :: * pmf) () const ) const
   {
      return this->min( std::mem_fn( pmf ) );
   }

   template<
      typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
      typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
   >
   R max( Unary unary_op = {} ) const
   {
      return this->accumulate(
         std::numeric_limits< R >::lowest(),
         (const R&(*)(const R&, const R&)) std::max,
         unary_op
      );
   }

   template<
      typename R2, typename C,
      typename R = R2
   >
   R max( R2 (C :: * pmf) () const ) const
   {
      return this->max( std::mem_fn( pmf ) );
   }

   template<
      typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
      typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
   >
   R sum( Unary unary_op = {} ) const
   {
      return this->accumulate(
         R{ 0 },
         std::plus< R >{},
         unary_op
      );
   }

   template<
      typename R2, typename C,
      typename R = R2
   >
   R sum( R2 (C :: * pmf) () const ) const
   {
      return this->sum( std::mem_fn( pmf ) );
   }
};

template< typename Iterator>
IteratorRange< Iterator >
make_iterator_range( const Iterator &i1, const Iterator &i2 )
{
   return { i1, i2 };
}

template< typename Container >
IteratorRange< typename Container::iterator >
make_iterator_range( Container &container )
{
   return { container.begin(), container.end() };
}

template< typename Container >
IteratorRange< typename Container::const_iterator >
make_iterator_range( const Container &container )
{
   return { container.begin(), container.end() };
}

// A utility function building a container of results
template< typename Container, typename Iterator, typename Function >
Container transform_range( Iterator first, Iterator last, Function &&fn )
{
   Container result;
   std::transform( first, last, std::back_inserter( result ), fn );
   return result;
}
// A utility function, often constructing a vector from another vector
template< typename OutContainer, typename InContainer, typename Function >
OutContainer transform_container( InContainer &inContainer, Function &&fn )
{
   return transform_range<OutContainer>(
      inContainer.begin(), inContainer.end(), fn );
}

// Extend wxArrayString with move operations and construction and insertion from
// std::initializer_list
class wxArrayStringEx : public wxArrayString
{
public:
   using wxArrayString::wxArrayString;
   wxArrayStringEx() = default;

   template< typename Iterator >
   wxArrayStringEx( Iterator start, Iterator finish )
   {
      this->reserve( std::distance( start, finish ) );
      while( start != finish )
         this->push_back( *start++ );
   }

   template< typename T >
   wxArrayStringEx( std::initializer_list< T > items )
   {
      this->reserve( this->size() + items.size() );
      for ( const auto &item : items )
         this->push_back( item );
   }

   // The move operations can take arguments of the base class wxArrayString
   wxArrayStringEx( wxArrayString &&other )
   {
      swap( other );
   }

   wxArrayStringEx &operator= ( wxArrayString &&other )
   {
      if ( this != &other ) {
         clear();
         swap( other );
      }
      return *this;
   }

   using wxArrayString::insert;

   template< typename T >
   iterator insert( const_iterator pos, std::initializer_list< T > items )
   {
      const auto index = pos - ((const wxArrayString*)this)->begin();
      this->wxArrayString::Insert( {}, index, items.size() );
      auto result = this->begin() + index, iter = result;
      for ( auto pItem = items.begin(), pEnd = items.end();
         pItem != pEnd;
         ++pItem, ++iter
      ) {
         *iter = *pItem;
      }
      return result;
   }
};

#endif // __AUDACITY_MEMORY_X_H__
