/*
 * See the files COPYING and README for copyright information and how to reach
 * the author.
 *
 *  $Id: menubase.c,v 1.2 2006/05/16 17:29:04 lordjaxom Exp $
 */

#include "menubase.h"
#include "manager.h"
#include "menuburn.h"
#include "menuitems.h"
#include "proctools/logger.h"
#include <vdr/interface.h>

namespace vdr_burn
{

	using namespace std;
	using proctools::logger;

	namespace menu
	{

		// --- starter --------------------------------------------------------

		const string starter::strings[starter::count] = 
				{ string(), "Recordings", "List", "Status" };
		starter* starter::m_instance = 0;
		
		starter::starter(void):
			cOsdMenu(""),
			m_display(none)
		{
			m_instance = this;
			if (manager::get_is_busy())
				m_nextDisplay = status;
			else if (pagebase::m_pending != 0 && 
					pagebase::m_pending->get_recordings().size() > 0)
				m_nextDisplay = job;
			else
				m_nextDisplay = recordings;
			show_menu();
		}

		starter::~starter()
		{
			m_instance = 0;
		}

		string starter::get_next_display(void)
		{
			display next = display( (m_instance->m_display + 1) % count );
			if (next == none)
				next = recordings;
			return tr(strings[next].c_str());
		}

		eOSState starter::show_menu(void)
		{
			m_display = m_nextDisplay;
			m_nextDisplay = none;

			switch (m_display)
			{
			case recordings:
				return AddSubMenu(new menu::recordings);

			case job:
				return AddSubMenu(new menu::job_editor);
				
			case status:
				return AddSubMenu(new menu::status);

			default:
				return osBack;
			}
		}

		eOSState starter::ProcessKey(eKeys key)
		{
			bool hadSubMenu = HasSubMenu();
			eOSState state = cOsdMenu::ProcessKey(key);

			if (hadSubMenu && !HasSubMenu())
				return show_menu();
			return state;
		}

		// --- pagebase -------------------------------------------------------
		
		job* pagebase::m_pending = 0;
		pagebase::user_wait pagebase::m_waitInfo;

		pagebase::pagebase(const string& title, int tab0, int tab1):
				cOsdMenu(title.c_str(), tab0, tab1)
		{
			if (m_pending == 0)
				m_pending = new job;
		}

		pagebase::~pagebase()
		{
		}

		void pagebase::set_help(const string& red, const string& green, 
								const string& yellow)
		{
			// <rant> must be constants, which is mentioned inside the impl,
			// not any documentation or so... well we assume, since we are in
			// the foreground thread, that the constants are not used anymore 
			// so it is safe to replace the strings here before giving the new
			// constants to the core
			m_red = red;
			m_green = green;
			m_yellow = yellow;
			m_blue = starter::get_next_display();

			SetHelp(m_red.empty() ? 0 : m_red.c_str(), 
					m_green.empty() ? 0 : m_green.c_str(), 
					m_yellow.empty() ? 0 : m_yellow.c_str(),
					m_blue.c_str());
		}

		void pagebase::set_current(int current)
		{
			if (current == -1 || Get(current) == 0) {
				current = 0;
				while (Get(current) != 0 && !Get(current)->Selectable())
					++current;
			}
			if (Get(current) != 0)
				SetCurrent(Get(current));
		}

		void pagebase::set_current(const item_position& current_)
		{
			set_current(m_positions.get_nearest(current_));
		}

		void pagebase::display(void)
		{
			set_help_keys();
			Display();
		}

		eOSState pagebase::dispatch_key(eKeys key)
		{
			switch (key) {
			case kOk:     return ok_pressed();
			case kRed:    return red_pressed();
			case kGreen:  return green_pressed();
			case kYellow: return yellow_pressed();
			case kNone:   check_waiting_user(); return osContinue; //return menu_update();
			default:      break;

			case kBlue:
				starter::cycle_display();
				return osBack;
			}
			return osUnknown;
		}

		eOSState pagebase::ProcessKey(eKeys key)
		{
			bool hadSubMenu = HasSubMenu();
			if (!hadSubMenu && key == kBack && !menu_closing())
				return osContinue;
				
			int current = Current();
			eOSState state = cOsdMenu::ProcessKey(key);

			if (hadSubMenu && HasSubMenu())
				return state;
			
			if (state == osUnknown)
				state = dispatch_key(key);
			else if (state == osContinue && 
					(current != Current() || key == kOk))
				set_help_keys();
			menu_update();
			return state;
		}

		bool pagebase::wait_for_user(const std::string& message)
		{
			logger::debug("wait_for_user");
			cMutexLock lock(&m_waitInfo.lock);
			
			m_waitInfo.waiting = true;
			m_waitInfo.message = message;
			m_waitInfo.condition.Wait(m_waitInfo.lock);
			logger::debug("finished waiting");
			m_waitInfo.waiting = false;

			return m_waitInfo.result;
		}

		void pagebase::check_waiting_user(void)
		{
			cMutexLock lock(&m_waitInfo.lock);

			if (m_waitInfo.waiting) {
				m_waitInfo.result = 
						Interface->Confirm(m_waitInfo.message.c_str(), 3600);
				m_waitInfo.condition.Broadcast();
			}
		}
			
		void pagebase::add_label(const char* text)
		{
			Add(new menu::text_item(text));
			m_positions.add(label, text);
		}
			
		void pagebase::add_item(recording_list::iterator& rec)
		{
			Add(new menu::recording_edit_item(rec));
			m_positions.add(recording, rec->get_filename());
		}

		void pagebase::add_item(const char* name, char* value, int length, const char* allowed)
		{
			Add(new cMenuEditStrItem(name, value, length, allowed));
			m_positions.add(setup, name);
		}
			
		void pagebase::add_item(const char* name, int& value, int count, const char* const* strings)
		{
			Add(new cMenuEditStraItem(name, &value, count, strings));
			m_positions.add(setup, name);
		}
			
		void pagebase::add_item(const char* name, int& value, const char* yes, const char* no)
		{
			Add(new cMenuEditBoolItem(name, &value, yes, no));
			m_positions.add(setup, name);
		}

	}
}
