#ifndef MOVIE_HPP
#define MOVIE_HPP

#include "config.h"

#include "module.hpp"
#include "options.hpp"
#include "config.hpp"
#include "gettext.hpp"

#include "imdb.hpp"

#include <stack>
#include <vector>
#include <list>

class Movie : public Module 
{
private:
  Movie();

  // commands
#ifdef use_graphical_movie
  void reget_movie_information();
  void print_info();
  void enter_dir();
  void go_back();
#else
  void enter_dir();
  void go_back();
#endif
  void action_play();
  void options();
  void search_func();
  void exit();
  
  bool exit_loop;

  bool search_compare(const Entry& s);
  std::string get_name_from_file(const Entry& e);

  void print(const std::vector<Entry>& files);
  void print_movie_element(const Entry& r, const Entry& position, int y);

#ifdef use_graphical_movie
  bool imdb_search_mainloop(const std::string& search_word, CIMDBMovie &m);
  Input imdb_search_screen(std::string search_word, IMDB_MOVIELIST results, int position, Overlay& o);
  void print_information();
  void graphical_print(const std::vector<CIMDBMovie>& files);
#endif

  enum SUBTYPE { IDX, SRT, NOSUB };

  // returns a pair of type, path_to_subtitles
  std::pair<SUBTYPE, std::vector<std::string> > find_subtitles(const std::string& dir);

  // playback
  void playmovie(const Entry file);
  void play_dvd_helper(const std::string& device);
#ifdef use_media
  void playcd(int count);
  void playvcd();
  void playdvd();
#endif

#ifdef use_media
  // dir
  std::string testdir(int *count);
#endif

  Entry addfile(const std::string& name, const MyPair& filetype);
  Entry add_dir(const std::string& filename);

#ifdef use_graphical_movie
  std::vector<CIMDBMovie> rdir(const std::string& argv);
  std::vector<CIMDBMovie> parse_dir(const std::list<std::string>& dirs);
#else
  std::vector<Entry> rdir(const std::string& argv);
  std::vector<Entry> parse_dir(const std::list<std::string>& dirs);
#endif

  // for saving information about how you traverse a filesystem a stack is a
  // much better solution. The first element is the dirs and the next is the
  // position
  std::stack<std::pair<std::list<std::string>, int > > folders;

#ifdef use_graphical_movie
  std::vector<CIMDBMovie> files;
#else
  std::vector<Entry> files;
#endif

#ifdef use_graphical_movie
  int image_width;
  int image_height;
  int image_height_all_eks_text;

  // including text and space around image
  int image_width_all;
  int image_height_all;
  int image_height_all_search;

  int images_per_row;
  int rows;
  int rows_search;

  int y_start;

  CIMDB imdb;
#endif

  void load_options();

  class MovieOpts : public Options 
  {
  public:
    MovieOpts();
    ~MovieOpts();

    std::string audio_mode() 
    {
      std::string temp = val[2]->values[val[2]->pos];

      if (temp == gettext("5.1 digital"))
	return conf->p_audio_mode_5d();
      else if (temp == gettext("5.1 analog"))
	return conf->p_audio_mode_5a();
      else if (temp == gettext("stereo"))
	return conf->p_audio_mode_2();
      else
	return "";
    }

    std::string dvd_audio_lang() 
    {
      if (conf->p_dvd_player() == MPLAYER)
	return val[3]->values[val[3]->pos];
      else
	return "";
    }

    std::string sub_lang() 
    {
      return val[base + 4]->english_values[val[base + 4]->pos];
    }
    
    std::string vcdtitle() 
    {
      if (conf->p_movie_player() == MPLAYER)
	return val[base + 5]->values[val[base + 5]->pos];
      else
	return "";
    }

    std::string dvdtitle() 
    {
      if (conf->p_dvd_player() == MPLAYER)
	return val[base + 6]->values[val[base + 6]->pos];
      else
	return "";
    }

    std::vector<Option*> values() 
    {
      return val;
    }

  private:
    void read_dirs();

    int base;

    Option *reload_p, *audio_mode_p, *dvd_audio_lang_p, *sub_lang_p, *vcdtitle_p, *dvdtitle_p;
  };

  struct file_sort
  {
    bool operator()(const Entry& lhs, const Entry& rhs);
  };

public:
  // singleton
  static Movie& get_instance();

  bool imdb_warning;

  int files_size() { return files.size(); }

  void reset();

  void load_current_dirs();
  void read_dirs();

#ifdef use_media
  void determine_media();
#endif

#ifdef use_graphical_movie
  std::string imdb_dir;
#endif

  std::string mainloop();

  MovieOpts opts;
};

#endif
