#include "config.h"

#include "config.hpp"

#include "audio.hpp"
#include "audio_s.hpp"
#include "gettext.hpp"

#ifdef player_gstreamer
#include "gstreamer.hpp"
#endif
#ifdef player_xine
#include "xine.hpp"
#endif
#ifdef player_alsaplayer
#include "alsaplayer.hpp"
#endif

#include <iostream>

using std::vector;
using std::string;

Audio_s* Audio_s::instance = 0;

Audio_s* Audio_s::get_instance() 
{
  if (instance == 0) {
    instance =  new Audio_s;
  }
  return instance;
}

// destructor
Audio_s::~Audio_s() 
{
  instance = 0;

  Config *conf = Config::get_instance();
  conf->s_audio_started(false);

  delete p;

#ifdef use_imms
  delete imms;
#endif
}

Audio_s::Audio_s() 
  : playback("playback"), has_played(false), 
    playback_fullscreen("playback_fullscreen"), playback_fullscreen_shown(false), fullscreen_info(false), 
    volume("volume"), volume_shown(false), 
    playing(false), paused(false)
{
#ifdef use_imms
  imms = new Imms();
#ifdef use_xidle
  imms->setup(true);
#else
  imms->setup(false);
#endif
  imms_cur_path = "";
#endif

  Config *conf = Config::get_instance();

#ifdef player_xine
  Overlay overlay("dialog");
  DialogStepPrint pdialog(gettext("Initializing Xine"), overlay);

  if (conf->p_priority_change()) 
    nice(-15); // Temporary raise priorities for Xine

  p = new Xine;

  if (conf->p_priority_change())
    nice(15); //and back down again
 
  pdialog.print_step2();
#endif

#ifdef player_alsaplayer
  p = new Alsaplayer;
#endif

#ifdef player_gstreamer
  p = new Gst;
#endif

  conf->s_audio_started(true);
}

void Audio_s::add_track_to_played(const Simplefile& e) 
{
  std::stack<Simplefile> temp = played_tracks;

  bool found = false;
  while (!temp.empty()) {
    Simplefile top = temp.top();
    temp.pop();
    if (top == e)
      found = true;
  }

  if (!found)
    played_tracks.push(e);
}

void Audio_s::remove_track_from_played(const Simplefile& e)
{
  std::stack<Simplefile> temp;
  
  while (!played_tracks.empty()) {
    Simplefile top = played_tracks.top();
    if (top != e)
      temp.push(top);
    played_tracks.pop();
  }

  played_tracks = temp;
}

Simplefile Audio_s::prev_track_played() 
{
  Simplefile e;
  
  if (played_tracks.size() == 0)
    return e;
  else {
    e = played_tracks.top();
    played_tracks.pop();
    return e;
  }
}

void Audio_s::add_track_to_queue(const Simplefile& e)
{
  if (queue_pos(e) == 0) // not already queued
    queued_tracks.push_back(e);
}

void Audio_s::remove_track_from_queue(const Simplefile& e)
{
  for (std::list<Simplefile>::iterator i = queued_tracks.begin(),
	 iend = queued_tracks.end(); i != iend; ++i)
    if (e == *i) {
      queued_tracks.erase(i);
      break;
    }
}

Simplefile Audio_s::next_in_queue()
{
  Simplefile q = queued_tracks.front();
  queued_tracks.pop_front();
  return q;
}

int Audio_s::queue_size()
{
  return queued_tracks.size();
}

int Audio_s::queue_pos(const Simplefile& s)
{
  int pos = 0;
  for (std::list<Simplefile>::const_iterator i = queued_tracks.begin(),
	 iend = queued_tracks.end(); i != iend; ++i) {
    ++pos;
    if (s == *i)
      return pos;
  }

  return 0;
}

void Audio_s::remove_queued_tracks()
{
  queued_tracks.clear();
}

bool Audio_s::check_repeat()
{
  Audio *audio = Audio::get_instance();

  if (audio->playlist_size() == 0)
    return false;

  bool status = true;

  if (!conv::stob(audio->opts.repeat())) {
    if (audio->opts.shuffle() == gettext("off")
	&& p->p_cur_nr() == audio->playlist.back())
      status = false;
    else if (audio->opts.shuffle() != gettext("off") 
	     && played_tracks.size() >= audio->playlist_size()) {
      if (audio->opts.shuffle() == gettext("real random"))
	status = true;
      else
	status = false;
    } else
      status = true;
    
    if (!status)
      empty_played_tracks();

  } else {
    if (played_tracks.size() > audio->playlist_size())
      empty_played_tracks();
  }

  return status;
}

bool Audio_s::check_shutdown()
{
  Audio *audio = Audio::get_instance();
  return conv::stob(audio->opts.shutdown());
}

void Audio_s::empty_played_tracks()
{
  while (!played_tracks.empty())
    played_tracks.pop();
}
