#pragma once
/*
 *      Copyright (C) 2010-2012 Team XBMC
 *      http://xbmc.org
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with XBMC; see the file COPYING.  If not, see
 *  <http://www.gnu.org/licenses/>.
 *
 */

#include <list>
#include <map>

#include "system.h"
#include "threads/CriticalSection.h"

#include "../AEAudioFormat.h"

typedef std::pair<std::string, std::string> AEDevice;
typedef std::vector<AEDevice> AEDeviceList;

/* forward declarations */
class IAEStream;
class IAESound;
class IAEPacketizer;

/* sound options */
#define AE_SOUND_OFF    0 /* disable sounds */
#define AE_SOUND_IDLE   1 /* only play sounds while no streams are running */
#define AE_SOUND_ALWAYS 2 /* always play sounds */

/**
 * IAE Interface
 */
class IAE
{
protected:
  friend class CAEFactory;

  IAE() {}
  virtual ~IAE() {}

  /**
   * Returns true when it should be possible to initialize this engine, if it returns false
   * CAEFactory can possibly fall back to a different one
   */
  virtual bool CanInit() { return true; }

  /**
   * Initializes the AudioEngine, called by CFactory when it is time to initialize the audio engine.
   * Do not call this directly, CApplication will call this when it is ready
   */
  virtual bool Initialize() = 0;
public:
  /**
   * Called when the application needs to terminate the engine
   */
  virtual void Shutdown() { }

  /**
   * Suspends output and de-initializes sink
   * Used to avoid conflicts with external players or to reduce power consumption
   * @return True if successful
   */
  virtual bool Suspend() = 0;

  /**
   * Resumes output and re-initializes sink
   * Used to resume output from Suspend() state above
   * @return True if successful
   */
  virtual bool Resume() = 0;

  /**
   * Get the current Suspend() state
   * Used by players to determine if audio is being processed
   * Default is true so players drop audio or pause if engine unloaded
   * @return True if processing suspended
   */
  virtual bool IsSuspended() {return true;}
  
  /**
   * Callback to alert the AudioEngine of setting changes
   * @param setting The name of the setting that was changed
   */
  virtual void OnSettingsChange(const std::string& setting) {}

  /**
   * Returns the current master volume level of the AudioEngine
   * @return The volume level between 0.0 and 1.0
   */
  virtual float GetVolume() = 0;

  /**
   * Sets the master volume level of the AudioEngine
   * @param volume The new volume level between 0.0 and 1.0
   */
  virtual void SetVolume(const float volume) = 0;

  /**
   * Set the mute state (does not affect volume level value)
   * @param enabled The mute state
   */
  virtual void SetMute(const bool enabled) = 0;

  /**
   * Get the current mute state
   * @return The current mute state
   */
  virtual bool IsMuted() = 0;

  /**
   * Sets the sound mode
   * @param mode One of AE_SOUND_OFF, AE_SOUND_IDLE or AE_SOUND_ALWAYS
   */
  virtual void SetSoundMode(const int mode) = 0;

  /**
   * Creates and returns a new IAEStream in the format specified, this function should never fail
   * @param dataFormat The data format the incoming audio will be in (eg, AE_FMT_S16LE)
   * @param sampleRate The sample rate of the audio data (eg, 48000)
   * @prarm encodedSampleRate The sample rate of the encoded audio data if AE_IS_RAW(dataFormat)
   * @param channelLayout The order of the channels in the audio data
   * @param options A bit field of stream options (see: enum AEStreamOptions)
   * @return a new IAEStream that will accept data in the requested format
   */
  virtual IAEStream *MakeStream(enum AEDataFormat dataFormat, unsigned int sampleRate, unsigned int encodedSampleRate, CAEChannelInfo channelLayout, unsigned int options = 0) = 0;

  /**
   * This method will remove the specifyed stream from the engine.
   * For OSX/IOS this is essential to reconfigure the audio output.
   * @param stream The stream to be altered
   * @return NULL
   */
  virtual IAEStream *FreeStream(IAEStream *stream) = 0;

  /**
   * Creates a new IAESound that is ready to play the specified file
   * @param file The WAV file to load, this supports XBMC's VFS
   * @return A new IAESound if the file could be loaded, otherwise NULL
   */
  virtual IAESound *MakeSound(const std::string &file) = 0;

  /**
   * Free the supplied IAESound object
   * @param sound The IAESound object to free
   */
  virtual void FreeSound(IAESound *sound) = 0;

  /**
   * Callback by CApplication for Garbage Collection. This method is called by CApplication every 500ms and can be used to clean up and free no-longer used resources.
   */
  virtual void GarbageCollect() = 0;

  /**
   * Enumerate the supported audio output devices
   * @param devices The device list to append supported devices to
   * @param passthrough True if only passthrough devices are wanted
   */
  virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough) = 0;

  /**
   * Returns the default audio device
   * @param passthrough True if the default passthrough device is wanted
   * @return the default audio device
   */
  virtual std::string GetDefaultDevice(bool passthrough) { return "default"; }

  /**
   * Returns true if the AudioEngine supports AE_FMT_RAW streams for use with formats such as IEC61937
   * @see CAEPackIEC61937::CAEPackIEC61937()
   * @returns true if the AudioEngine is capable of RAW output
   */
  virtual bool SupportsRaw() { return false; }
};

