/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2008/X/X - 2016/12/01
/// 
/// @brief  DirectSound 静的バッファ周り
/// 
/// ****************************************************************************
#pragma once

#include "CPL_DX_SoundBase.h"
#include "CPL_DX_SoundBase.cpp"

namespace CPL {
namespace DX {
namespace Audio {


// _____________________________________________________________________________
/// @brief SoundPlayerEntity_for_Decompressed実体定義
///
// *****************************************************************************
class SoundPlayerEntity_for_Decompressed
  : public baseSoundPlayer::Entity_
{
public:
  // _____________________________________________________________________________
  /// @brief サウンドバッファの作成
  /// 
  /// @param[in] in_cp_dx_sound
  ///   : DirectSoundオブジェクトのスマートポインタを指定します。
  /// @param[in] in_sp_sound_stream
  ///   : サウンドマネージャオブジェクトのスマートポインタを指定します。
  /// @param[in] in_flags
  ///   : バッファの能力を示すフラグの組み合わせを指定します。\n
  ///   : DSBUFFERDESC構造体のdwFlagsに渡されます。\n
  ///   : 詳しくはDSBUFFERDESC::dwFlagsを検索してください。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  bool
    Create
      ( _in<CpDXSound>                     in_cp_dx_sound
      , _in<sdptr<Core::BaseSoundManager>> in_sp_sound_stream
      , _in<DWORD>                         in_flags
      )
  {
    m_cp_dsound_buf = nullptr; // 解放＆初期化

    m_cp_dsound  = in_cp_dx_sound;
    m_sp_snd_mng = in_sp_sound_stream;

    // フォーマット取得。
    auto* wfex      = in_sp_sound_stream->GetWaveFormatEx();
    int   data_size = in_sp_sound_stream->GetBufferSizePCM();
    if( data_size < 0 )
    {
      return false;
    }

    // DirectSoundBuffer設定
    DSBUFFERDESC desc;
    ::memset( &desc, 0, sizeof(desc) );
    desc.dwSize        = sizeof(desc);
    desc.dwFlags       = in_flags;
    desc.dwBufferBytes = data_size;
    desc.lpwfxFormat   = reinterpret_cast<WAVEFORMATEX*>(wfex);
    // DirectSoundバッファ作成。
    IDirectSoundBuffer* ptr_dsb_tmp = nullptr;
    HRESULT hr = m_cp_dsound->CreateSoundBuffer( &desc, &ptr_dsb_tmp, nullptr );
    if( ptr_dsb_tmp )
    {
      hr = ptr_dsb_tmp->QueryInterface
             ( IID_IDirectSoundBuffer8, (void**)&m_cp_dsound_buf );
    }
    ptr_dsb_tmp->Release();

    if( FAILED(hr) )
    {
      CPL_THROW("サウンドバッファの作成に失敗");
      return false;
    }

    // データ書き込み。
    in_sp_sound_stream->SeekSetPCM( 0 );
    WriteDsBuffer( 0, *m_sp_snd_mng, data_size );

    return true;
  }

  
  //// _____________________________________________________________________________
  ///// @brief サウンドバッファの作成　※ CSC指定バージョン
  ///// 
  ///// @param[in] in_cp_dx_sound : DirectSoundオブジェクトのスマポ。
  ///// @param[in] in_csc_buf     : CSCバッファクラス。
  ///// @param[in] in_flags       : DSBUFFERDESC構造体のdwFlagsに渡す。
  //// _____________________________________________________________________________
  //bool
  //  Create
  //  ( cref<CpDXSound> in_cp_dx_sound,
  //    CscStm_cref     in_csc_buf,
  //    DWORD           in_flags )
  //{
  //  m_cp_dsound_buf = nullptr; // 解放＆初期化

  //  Core::WaveMemoryStream wave;
  //  try {
  //#if (CPL_CSC_VERSION == 1)

  //    in_csc_buf.Decode( wave );

  //#elif (CPL_CSC_VERSION == 2)

  //    in_csc_buf.Decode2( wave );

  //#endif
  //  }
  //  catch(...)
  //  {
  //    return false;
  //  }

  //  return Create( in_cp_dx_sound, wave, in_flags );

  ///*  // フォーマット取得
  //  const WIN::WaveInfo& wavInfo = wave.GetWaveInfo();
  //  const WaveFormatEx&  wfex    = wavInfo.GetWaveFormatEX();
  //
  //  const WIN::WaveInfo::ChunkOffs* pData = pWave->FindChunk( "data" );
  //  if( !pData )
  //  {
  //    return false;
  //  }

  //  // DirectSoundBuffer設定
  //  ::memset( &desc, 0, sizeof(desc) );
  //  desc.dwSize        = sizeof(desc);
  //  desc.dwFlags       = Flags;
  //  desc.dwBufferBytes = pData->size;
  //  desc.lpwfxFormat   = &wfex;
  //  // バッファ作成
  //  IDirectSoundBuffer* pIDSndBuf;
  //  HRESULT hr = m_cp_dsound->CreateSoundBuffer( &desc, &pIDSndBuf, nullptr );
  //  if( FAILED(hr) )
  //  {
  //    CPL_THROW("サウンドバッファの作成に失敗", __FILE__, __LINE__);
  //    return false;
  //  }
  //  m_cp_dsound_buf = pIDSndBuf;

  //  // データ書き込み
  //  WriteDsBuffer( 0, wave.GetDataStream()->GetTopAddr(), pData->size );
  //*/
  ////  return true;
  //}

  
  // _____________________________________________________________________________
  /// @brief サウンドバッファの作成　※ ファイル指定バージョン
  /// 
  /// @param[in] in_cp_dx_sound : DirectSoundオブジェクトのスマポ。
  /// @param[in] in_path        : ファイルへのパス。
  /// @param[in] in_mask        : ファイルがCSCの場合、マスク文字列を指定する。
  /// @param[in] in_flags       : DSBUFFERDESC構造体のdwFlagsに渡す。
  /// 
  /// @retval true  : 作成成功。
  /// @retval false : 作成失敗。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  bool
    Create
      ( _in<CpDXSound    > in_cp_dx_sound
      , pin<str_type     > in_path
      , _in<Core::StringA> in_mask
      , _in<DWORD        > in_flags
      )
  {
    // 拡張子取得
    Core::String str = in_path;
    Core::String ext;
    str.FindEndBack( ext, SwS('.'), false );

    if( _tcsicmp( ext, SwS("wav") ) == 0  ||
        _tcsicmp( ext, SwS("wave") ) == 0 )
    {
      auto sp_snd_buf  = CPL_MAKE_SHARED( Core::FileStream, in_path, Core::FileStream::kREAD_BINARY );
      auto sp_wave_mng = CPL_MAKE_SHARED( Core::WaveManager, sp_snd_buf );

      return Create( in_cp_dx_sound, sp_wave_mng, in_flags );
    }
#ifdef CPL_USE_OGG_VORBIS
    else
    if( _tcsicmp( ext, SwS("ogg") ) == 0  ||
        _tcsicmp( ext, SwS("oga") ) == 0 )
    {
      auto sp_snd_buf = CPL_MAKE_SHARED( Core::FileStream, in_path, Core::FileStream::kREAD_BINARY );
      auto sp_ov_mng  = CPL_MAKE_SHARED( Core::OvManager, sp_snd_buf );

      return Create( in_cp_dx_sound, sp_ov_mng, in_flags );
    }
#endif
  //  ef( ext == SwS("csc")  ||  ext == SwS("csc") )
  //  {
  //    Core::WaveMemoryStream wave_buf;
  //    try {
  //#if (CPL_CSC_VERSION == 1)
  //      Core::CscMemoryStream( in_path, in_mask ).Decode( wave_buf );
  //#elif (CPL_CSC_VERSION == 2)
  //      Core::CscMemoryStream( in_path, in_mask ).Decode2( wave_buf );
  //#endif
  //    }
  //    catch( ... )
  //    {
  //      return false;
  //    }

  //    return Create( in_cp_dx_sound, wave_buf, in_flag );
  //  }
    return false;
  }

  // _____________________________________________________________________________
  /// @brief SoundPlayerEntity_for_Decompressed:デフォルトコンストラクタ
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SoundPlayerEntity_for_Decompressed()
  {}

  // _____________________________________________________________________________
  /// @brief WAVEストリーム対応コンストラクタ
  /// @copydetails Create(_in<CpDXSound>,_in<sdptr<Core::BaseSoundManager>>,_in<DWORD>)
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SoundPlayerEntity_for_Decompressed
  ( _in<CpDXSound>                     in_cp_dx_sound
  , _in<sdptr<Core::BaseSoundManager>> in_sp_sound_stream
  , _in<DWORD>                         in_flags
  )
  {
    CPL_THROW_IF
      ( !Create( in_cp_dx_sound, in_sp_sound_stream, baseSoundPlayer::DEFAULt_FLAGS_ )
      , "実体の生成に失敗"
      );
  }
  
  //// _____________________________________________________________________________
  ///// @brief CSCストリーム対応コンストラクタ。
  ///// @copydetails Create(cref<CpDXSound>,CscStm_cref,DWORD)
  //// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  //SoundPlayerEntity_for_Decompressed
  //( cref<CpDXSound> in_cp_dx_sound,
  //  CscStm_cref     in_csc_buf,
  //  DWORD           in_flags )
  //{
  //  CPL_THROW_IF(
  //    !Create( in_cp_dx_sound, in_csc_buf, baseSoundPlayer::DEFAULt_FLAGS_ ),
  //    "実体の生成に失敗" );
  //}

  // _____________________________________________________________________________
  /// @brief SoundPlayerEntity_for_Decompressed:ファイル読み込み対応コンストラクタ
  /// @copydetails Create(_in<CpDXSound>,pin<str_type>,_in<Core::StringA>,_in<DWORD>)
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  SoundPlayerEntity_for_Decompressed
  ( _in<CpDXSound    > in_cp_dx_sound
  , pin<str_type     > in_path
  , _in<Core::StringA> in_mask
  , _in<DWORD        > in_flags
  )
  {
    CPL_THROW_IF
      ( !Create( in_cp_dx_sound, in_path, in_mask, baseSoundPlayer::DEFAULt_FLAGS_ )
      , "実体の生成に失敗"
      );
  }
  
  // _____________________________________________________________________________
  /// @brief デストラクタ
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ~SoundPlayerEntity_for_Decompressed()
  {}
};




} // namespace Audio
} // namespace DX
} // namespace CPL
