// for prefix
#include "config.h"

#include "input.hpp"

#include "config.hpp"
#include "common.hpp"

#include "replay.hpp"

#include "gettext.hpp"

#include <fstream>
#include <sstream>
#include <iostream>

using std::string;

string Input::to_string() const
{
  return mode + "," + key + "," + command + "," + name + "," + conv::btos(multiple);
}

Input::Input()
{}

Input::Input(string& s)
{
  string::size_type comma = s.find(",");
  mode = s.substr(0, comma);
  s = s.substr(comma+1);

  comma = s.find(",");
  key = s.substr(0, comma);
  s = s.substr(comma+1);

  comma = s.find(",");
  command = s.substr(0, comma);
  s = s.substr(comma+1);

  comma = s.find(",");
  name = s.substr(0, comma);
  s = s.substr(comma+1);

  multiple = conv::stob(s);
}

Input_master* Input_master::instance = 0;

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

Input Input_device::get_input()
{
  input_done_.wait();
  input_done_.reset();
  input_ready.signal();

  register_keypress(input);

  ReplaySaver *r = ReplaySaver::get_instance();
  r->add_event(input);

  return input;
}

Input_device::Input_device()
  : accept_all(false)
{}

Input_master::Input_master()
{
  parse_keys();
}

std::string Input_master::find_shortcut(const std::string& command)
{
  input_list clist = cur_list();
  for (input_list::const_iterator i = clist.begin(), iend = clist.end();
       i != iend; ++i)
    if (command == i->command)
      return i->key;

  std::cout << "something wrong:" << command << " not found" << std::endl;
  return "";
}

void Input_master::parse_keys()
{
  Config *config = Config::get_instance();

  string input = "keyboard"; // default

  if (config->p_input() == LIRC)
    input = "lirc";
  else if (config->p_input() == EVDEV)
    input = "evdev";

  input = config->p_homedir() + "input-" + input;

  std::ifstream In(input.c_str());   //create an input file stream

  if(!In){
    DebugPrint perror(gettext("Input configuration file not found ") + 
                      input, Print::DEBUGGING, DebugPrint::CRITICAL, "INPUT");
  } else {

    string str;

    bool version_correct = false;

    bool graphical = false;

#ifdef use_graphical_movie
    graphical = true;
#endif
#ifdef use_imms
    graphical = true;
#endif
  
    while (getline(In, str)) {
      // skips empty and strings which starts with a #
      if (str[0] != '#' && str.size() != 0)
	{
	  if (!version_correct) {
	    string::size_type p = str.find("=");
	    string param = str.substr(0, p-1);
	    string value = str.substr(p+2);

	    if (param == "version") {

	      if (value == MMS_INPUT_CONFIG_VERSION)
		version_correct = true;
	      else {
		DebugPrint perror(Print::DEBUGGING, DebugPrint::CRITICAL, "INPUT");
		perror.add_line(input + gettext(" is version ") + value + gettext(" and mms expecting version ") + MMS_INPUT_CONFIG_VERSION);
		perror.add_line(gettext("Please upgrade your input file"));
		perror.print();
		exit(1);
	      }

	      continue;

	    } else {
	      DebugPrint perror(Print::DEBUGGING, DebugPrint::CRITICAL, "INPUT");
	      perror.add_line(gettext("Version string not found"));
	      perror.add_line(gettext("Please upgrade your input file"));
	      perror.print();
	      exit(1);
	    }
	  }

	  string::size_type pos = str.find(",");

	  if (pos == string::npos) // bogus line
	    continue;

	  string mode = str.substr(0, pos);

	  string strlast = str.substr(pos+1);
	  string::size_type pos2 = strlast.find(",");

	  if (pos2 == string::npos) // bogus line
	    continue;

	  string strlast2 = strlast.substr(pos2+1);
	  string::size_type pos3 = strlast2.find(",");

	  string command = str.substr(pos+1, pos2);

	  string key, mult;
	  if (pos3 != string::npos) {
	    key = strlast.substr(pos2+1, pos3); // pos3 is relative to strlast2
	    mult = strlast2.substr(pos3+1);
	  } else {
	    key = strlast.substr(pos2+1);
	    mult = "";
	  }

	  bool multiple = false;

	  if (mult == "yes")
	    multiple = true;

	  Input putback;
	  putback.mode = mode;
	  putback.command = command;
	  putback.key = key;
	  putback.multiple = multiple;
     
	  if (command == "prev")putback.name=gettext("Previous");
	  else if (command == "next")putback.name=gettext("Next");
	  else if (command == "left")putback.name=gettext("Move left");
	  else if (command == "right")putback.name=gettext("Move right");
	  else if (command == "back")putback.name=gettext("Return to startmenu");
	  else if (command == "action")putback.name=gettext("Action");
	  else if (command == "second_action")putback.name=gettext("Extra menu");
	  else if (command == "options")putback.name=gettext("Options");
	  else if (command == "search")putback.name=gettext("Search");
	  else if (command == "page_down")putback.name=gettext("Next page");
	  else if (command == "page_up")putback.name=gettext("Previous page");
#ifdef use_sdl
	  else if (command == "fullscreen")putback.name=gettext("Fullscreen");
#endif
	  else if (command == "mode")putback.name=gettext("Playlist (toggle)");
	  else if (command == "playlist_mode")putback.name=gettext("Load/Save a playlist");
	  else if (command == "playlist_commands")putback.name=gettext("Playlist commands");
	  else if (command == "play")putback.name=gettext("Play");
	  else if (command == "pause" && mode == "audio_general")putback.name=gettext("Pause");
	  else if (command == "stop")putback.name=gettext("Stop");
	  else if (command == "ff")putback.name=gettext("Fast forward");
	  else if (command == "fb")putback.name=gettext("Fast backward");
	  else if (command == "prev_track")putback.name=gettext("Previous track");
	  else if (command == "next_track")putback.name=gettext("Next track");
	  else if (command == "vol+")putback.name=gettext("Increase volume");
	  else if (command == "vol-")putback.name=gettext("Decrease volume");
	  else if (command == "mute")putback.name=gettext("Mute");
	  else if (command == "move_up")putback.name=gettext("Move track up");
	  else if (command == "move_down")putback.name=gettext("Move track down");
	  else if (command == "delete")putback.name=gettext("Delete track");
	  else if (command == "queue")putback.name=gettext("En queue track");
	  else if (command == "clear_list")putback.name=gettext("Clear playlist");
	  else if (command == "save_playlist")putback.name=gettext("Save playlist");
	  else if (command == "pause" && mode == "pictures_fullscreen")putback.name=gettext("Pause slideshow");
	  else if (command == "rotate")putback.name=gettext("Rotate picture");
	  else if (command == "info" && graphical)putback.name=gettext("Print information");
	  else if (command == "accept")putback.name=gettext("Accept");
	  else if (command == "complete")putback.name=gettext("Complete");
	  else if (command == "erase")putback.name=gettext("Delete");
	  else if (command == "exit")putback.name=gettext("Exit");
#ifdef use_graphical_movie
	  else if (command == "reget")putback.name=gettext("Update IMDb information");
	  else if (command == "enter_dir")putback.name=gettext("Enter directory");
#endif

          else putback.name=command;

	  DebugPrint perror("Adding " + mode + " " + command + " " + key + " " +
			    putback.name, Print::INFO, DebugPrint::ALL, "INPUT");

	  if (mode == "general" || mode == "audio_general") {
	    startmenu.insert(std::make_pair(putback.key, putback));
	    startmenu_l.push_back(putback);

	    standard.insert(std::make_pair(putback.key, putback));
	    standard_l.push_back(putback);
	    
	    if (command == "action")
	      putback.name = gettext("Play movie");
	    movies.insert(std::make_pair(putback.key, putback));
	    movies_l.push_back(putback);

#ifdef use_graphical_movie
	    if (command == "action")
	      putback.name = gettext("Select movie");
	    movie_imdb.insert(std::make_pair(putback.key, putback));
	    movie_imdb_l.push_back(putback);
#endif

	    if (command == "action")
	      putback.name = gettext("Add to Playlist");
	    audio_add.insert(std::make_pair(putback.key, putback));
	    audio_add_l.push_back(putback);

	    if (command == "action")
	      putback.name = gettext("Play track");
	    playlist.insert(std::make_pair(putback.key, putback));
	    playlist_l.push_back(putback);

	    if (command == "action")
	      putback.name = gettext("Load");
	    playlist_load.insert(std::make_pair(putback.key, putback));
	    playlist_load_l.push_back(putback);

	    if (command == "action")
	      putback.name = gettext("Rotate");
	    pictures.insert(std::make_pair(putback.key, putback));
	    pictures_l.push_back(putback);

	    if (command == "action")
	      putback.name = gettext("View Information");
	    epg.insert(std::make_pair(putback.key, putback));
	    epg_l.push_back(putback);
	  } else if (mode == "graphical") {
#ifdef use_imms
	    audio_add.insert(std::make_pair(putback.key, putback));
	    playlist.insert(std::make_pair(putback.key, putback));
	    audio_add_l.push_back(putback);
	    playlist_l.push_back(putback);
#endif
#ifdef use_graphical_movie
	    movies.insert(std::make_pair(putback.key, putback));
	    movies_l.push_back(putback);
	  } else if (mode == "graphical_movie") {
	    movies.insert(std::make_pair(putback.key, putback));
	    movies_l.push_back(putback);
#endif
#ifdef use_imms
	  } else if (mode == "graphical_audio") {
	    audio_add.insert(std::make_pair(putback.key, putback));
	    audio_add_l.push_back(putback);
#endif
	  } else if (mode == "playlist_general") {
	    playlist.insert(std::make_pair(putback.key, putback));
	    playlist_load.insert(std::make_pair(putback.key, putback));
	    playlist_l.push_back(putback);
	    playlist_load_l.push_back(putback);
	  } else if (mode == "choose_playlist") {
	    playlist_load.insert(std::make_pair(putback.key, putback));
	    playlist_load_l.push_back(putback);
	  } else if (mode == "audio_add") {
	    audio_add.insert(std::make_pair(putback.key, putback));
	    audio_add_l.push_back(putback);
	  } else if (mode == "playlist") {
	    playlist.insert(std::make_pair(putback.key, putback));
	    playlist_l.push_back(putback);
	  } else if (mode == "pictures") {
	    pictures.insert(std::make_pair(putback.key, putback));
	    pictures_l.push_back(putback);
	  } else if (mode == "pictures_fullscreen") {
	    pictures.insert(std::make_pair(putback.key, putback));
	    pictures_l.push_back(putback);
	  } else if (mode == "epg") {
	    epg.insert(std::make_pair(putback.key, putback));
	    epg_l.push_back(putback);
	  } else if (mode == "search") {
	    search.insert(std::make_pair(putback.key, putback));
	    search_l.push_back(putback);
          } else
	    DebugPrint perror2(gettext("Unknown mode '") + mode + 
			       gettext("' in input file"), 
			       Print::DEBUGGING, DebugPrint::WARNING, "INPUT");
	}
    }
  }
}

input_list Input_master::cur_list() 
{
  if (cur_map == &startmenu)
    return startmenu_l;
  else if (cur_map == &standard)
    return standard_l;
  else if (cur_map == &movies)
    return movies_l;
#ifdef use_graphical_movie
  else if (cur_map == &movie_imdb)
    return movie_imdb_l;
#endif
  else if (cur_map == &audio_add)
    return audio_add_l;
  else if (cur_map == &playlist)
    return playlist_l;
  else if (cur_map == &playlist_load)
    return playlist_load_l;
  else if (cur_map == &pictures)
    return pictures_l;
  else if (cur_map == &epg)
    return epg_l;
  else if (cur_map == &search)
    return search_l;
  else
    DebugPrint perror(gettext("Unknown cur_map"),
		      Print::DEBUGGING, DebugPrint::WARNING, "INPUT");

  input_list l;
  return l;
}
