/* -*- mode: c++; tab-width: 4; c-basic-offset: 4 -*- */
/*
 * Copyright (C) 2005 Atmark <atmarkat _AT_ msn _DOT_ com>
 *                    AGAWA Koji <i _AT_ atty _DOT_ jp>
 *
 * 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 of the License, 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <qapplication.h>
#include "action.h"

/*! アクションの定義 */
// Next ID = 43 (アクションを追加した場合はこのコメントも編集してください)
const ActionManager::ActionDecl ActionManager::actionDecls_[] = {
//    ID,  Name
// 	{   0, QT_TR_NOOP("Quit") },
	{   1, QT_TR_NOOP("Playback/Play Or Pause") },
	{   2, QT_TR_NOOP("Playback/Stop") },
	{   3, QT_TR_NOOP("Playback/Next") },
	{   4, QT_TR_NOOP("Playback/Previous") },
	{   5, QT_TR_NOOP("Playback/Volume Up") },
	{   6, QT_TR_NOOP("Playback/Volume Down") },
// 	{   7, QT_TR_NOOP("Playback/Volume mute") },
	{  11, QT_TR_NOOP("Playback/Seek Ahead By 1 Second") },
	{  12, QT_TR_NOOP("Playback/Seek Ahead By 5 Seconds") },
	{  13, QT_TR_NOOP("Playback/Seek Ahead By 10 Seconds") },
	{  14, QT_TR_NOOP("Playback/Seek Ahead By 20 Seconds") },
	{  15, QT_TR_NOOP("Playback/Seek Ahead By 30 Seconds") },
	{  16, QT_TR_NOOP("Playback/Seek Ahead By 1 Minute") },
	{  17, QT_TR_NOOP("Playback/Seek Ahead By 2 Minutes") },
	{  18, QT_TR_NOOP("Playback/Seek Ahead By 5 Minutes") },
	{  19, QT_TR_NOOP("Playback/Seek Ahead By 10 Minutes") },
	{  20, QT_TR_NOOP("Playback/Seek Back By 1 Second") },
	{  21, QT_TR_NOOP("Playback/Seek Back By 5 Seconds") },
	{  22, QT_TR_NOOP("Playback/Seek Back By 10 Seconds") },
	{  23, QT_TR_NOOP("Playback/Seek Back By 20 Seconds") },
	{  24, QT_TR_NOOP("Playback/Seek Back By 30 Seconds") },
	{  25, QT_TR_NOOP("Playback/Seek Back By 1 Minute") },
	{  26, QT_TR_NOOP("Playback/Seek Back By 2 Minutes") },
	{  27, QT_TR_NOOP("Playback/Seek Back By 5 Minutes") },
	{  28, QT_TR_NOOP("Playback/Seek Back By 10 Minutes") },
	{  29, QT_TR_NOOP("Playlist/Add Directory...") },
	{  30, QT_TR_NOOP("Playlist/Add Files...") },
	{  31, QT_TR_NOOP("Playlist/Add Location...") },
	{  32, QT_TR_NOOP("Playlist/New") },
	{  33, QT_TR_NOOP("Playlist/Open...") },
	{  34, QT_TR_NOOP("Playlist/Save") },
	{  35, QT_TR_NOOP("Playlist/Save As...") },
// 	{  36, QT_TR_NOOP("Playlist/Clear") },
	{  37, QT_TR_NOOP("Playlist/Delete") },
	{  38, QT_TR_NOOP("Playlist/Move Back") },
	{  39, QT_TR_NOOP("Playlist/Move Forward") },
	{  50, QT_TR_NOOP("Playlist/Clear") },
	{  51, QT_TR_NOOP("Playlist/Cut") },
	{  52, QT_TR_NOOP("Playlist/Copy") },
	{  53, QT_TR_NOOP("Playlist/Paste") },
	{  54, QT_TR_NOOP("Playlist/Select All") },
	{  55, QT_TR_NOOP("Playlist/Deselect All") },
	{  56, QT_TR_NOOP("Playlist/Copy To On-The-Go Playlist") },
	{  57, QT_TR_NOOP("Playlist/Select Mode") },
	{  58, QT_TR_NOOP("Playlist/Multiselect Mode") },
	{  59, QT_TR_NOOP("Playlist/Move Item Mode") },
	{ 100, QT_TR_NOOP("Playlist/Focus Filterbox") },
	{ 101, QT_TR_NOOP("Playlist/Reset Filter") },
	{ 102, QT_TR_NOOP("Playlist/Play Selected Song") },
	{ 103, QT_TR_NOOP("Playlist/Reset Filter And Focus Filterbox") },
	{ 104, QT_TR_NOOP("Playlist/Focus Playlist") },
	{   8, QT_TR_NOOP("Playback/Turn On LCD") },
	{   9, QT_TR_NOOP("Playback/Turn Off LCD") },
	{  10, QT_TR_NOOP("Playback/Toggle PlayInfo") },
	{  40, QT_TR_NOOP("Playback/Toggle OSD") },
	{  41, QT_TR_NOOP("Playback/Increase Brightness") },
	{  42, QT_TR_NOOP("Playback/Decrease Brightness") },
	{ 200, QT_TR_NOOP("Display/Decrease Size") },
	{ 201, QT_TR_NOOP("Display/Increase Size") },
	{ 202, QT_TR_NOOP("Display/Toggle Fullscreen") },
	{ 203, QT_TR_NOOP("Display/Quickswitch Skin 1") },
	{ 204, QT_TR_NOOP("Display/Quickswitch Skin 2") },
	{ 205, QT_TR_NOOP("Display/Toggle Overview Visibility") },
	{ 300, QT_TR_NOOP("Playback/Toggle Play Order") },
	{ 301, QT_TR_NOOP("Playback/Toggle Random Play Order") },
	{ 400, QT_TR_NOOP("Overview/Focus Overview") },
	{ 500, QT_TR_NOOP("View/Current Playlist") },
	{ 501, QT_TR_NOOP("View/On-The-Go Playlist") },
	{ 502, QT_TR_NOOP("View/PlayInfo") },
	{  -1, "" }
};

void ActionManager::createDefaultHotKeyMap()
{
	static int GLOBAL = Configuration::HOTKEY_CONTEXT_GLOBAL,
		PLAYLIST = Configuration::HOTKEY_CONTEXT_PLAYLIST,
		VIDEO = Configuration::HOTKEY_CONTEXT_VIDEO,
		AUDIO = Configuration::HOTKEY_CONTEXT_AUDIO;

	addHotKey("Playback/Play Or Pause", Qt::Key_Space, GLOBAL);
	addHotKey("Playlist/Play Selected Song", Qt::Key_Return, GLOBAL);
	addHotKey("Playback/Stop", Qt::Key_Escape, GLOBAL);
	addHotKey("Playback/Next", Qt::Key_N, GLOBAL);
	addHotKey("Playback/Previous", Qt::Key_B, GLOBAL);
	addHotKey("Playback/Volume Up", Qt::Key_Up, VIDEO, AUDIO);
	addHotKey("Playback/Volume Up", Qt::SHIFT|Qt::Key_Up, PLAYLIST);
	addHotKey("Playback/Volume Up", Qt::Key_Q, GLOBAL);
	addHotKey("Playback/Volume Down", Qt::Key_Down, VIDEO, AUDIO);
	addHotKey("Playback/Volume Down", Qt::SHIFT|Qt::Key_Down, PLAYLIST);
	addHotKey("Playback/Volume Down", Qt::Key_A, GLOBAL);
	addHotKey("Playback/Seek Ahead By 10 Seconds", Qt::Key_Right, GLOBAL);
	addHotKey("Playback/Seek Ahead By 1 Minute", Qt::SHIFT|Qt::Key_Right, VIDEO, AUDIO);
	addHotKey("Playback/Seek Ahead By 1 Minute", Qt::CTRL|Qt::Key_Right, PLAYLIST);
	addHotKey("Playback/Seek Ahead By 5 Minutes", Qt::CTRL|Qt::Key_Right, VIDEO, AUDIO);
	addHotKey("Playback/Seek Ahead By 5 Minutes", Qt::ALT|Qt::Key_Right, PLAYLIST);
	addHotKey("Playback/Seek Back By 10 Seconds", Qt::Key_Left, GLOBAL);
	addHotKey("Playback/Seek Back By 1 Minute", Qt::SHIFT|Qt::Key_Left, VIDEO, AUDIO);
	addHotKey("Playback/Seek Back By 1 Minute", Qt::CTRL|Qt::Key_Left, PLAYLIST);
	addHotKey("Playback/Seek Back By 5 Minutes", Qt::CTRL|Qt::Key_Left, VIDEO, AUDIO);
	addHotKey("Playback/Seek Back By 5 Minutes", Qt::ALT|Qt::Key_Left, PLAYLIST);
	addHotKey("Playlist/Add Directory...", Qt::SHIFT|Qt::Key_D, PLAYLIST);
	addHotKey("Playlist/Add Files...", Qt::SHIFT|Qt::Key_F, PLAYLIST);
	addHotKey("Playlist/Add Location...", Qt::SHIFT|Qt::Key_L, PLAYLIST);
	addHotKey("Playlist/Open...", Qt::SHIFT|Qt::Key_O, PLAYLIST);
	addHotKey("Playlist/Save", Qt::SHIFT|Qt::Key_S, PLAYLIST);
	addHotKey("Playlist/Delete", Qt::Key_Delete, PLAYLIST);
	addHotKey("Playlist/Move Back", Qt::CTRL|Qt::Key_Up, PLAYLIST);
	addHotKey("Playlist/Move Forward", Qt::CTRL|Qt::Key_Down, PLAYLIST);
	addHotKey("Playlist/Focus Filterbox", Qt::Key_L, GLOBAL);
	addHotKey("Playlist/Reset Filter And Focus Filterbox", Qt::Key_Backspace, GLOBAL);	
	addHotKey("Playback/Turn On LCD", Qt::Key_4, GLOBAL);
	addHotKey("Playback/Turn Off LCD", Qt::Key_3, PLAYLIST, AUDIO);
	addHotKey("Playback/Toggle PlayInfo", Qt::SHIFT|Qt::Key_I, PLAYLIST, AUDIO);
	addHotKey("Playback/Toggle PlayInfo", Qt::Key_M, GLOBAL);
	addHotKey("Playback/Toggle OSD", Qt::Key_O, VIDEO);
	addHotKey("Playback/Decrease Brightness", Qt::Key_1, VIDEO);
	addHotKey("Playback/Increase Brightness", Qt::Key_2, VIDEO);
	addHotKey("Playback/Toggle Play Order", Qt::Key_P, GLOBAL);
	addHotKey("Playback/Toggle Random Play Order", Qt::Key_R, GLOBAL);
	addHotKey("Playback/Toggle Random Play Order", Qt::Key_Question, GLOBAL);
	addHotKey("Playback/Toggle Random Play Order", Qt::Key_Period, GLOBAL);
	addHotKey("Display/Decrease Size", 0x200F, GLOBAL);
	addHotKey("Display/Increase Size", 0x2010, GLOBAL);
	addHotKey("Display/Toggle Fullscreen", Qt::SHIFT|Qt::Key_Return, GLOBAL);
	addHotKey("Display/Toggle Fullscreen", Qt::Key_F, GLOBAL);
	addHotKey("Display/Toggle Overview Visibility", Qt::Key_I, PLAYLIST);
	addHotKey("Display/Quickswitch Skin 1", Qt::CTRL|Qt::Key_1, GLOBAL);
	addHotKey("Display/Quickswitch Skin 2", Qt::CTRL|Qt::Key_2, GLOBAL);
	addHotKey("Overview/Focus Overview", Qt::Key_O, GLOBAL);
	addHotKey("View/Current Playlist", Qt::Key_W, GLOBAL);
	addHotKey("View/On-The-Go Playlist", Qt::Key_E, GLOBAL);
	addHotKey("Playlist/Copy To On-The-Go Playlist", Qt::Key_C, GLOBAL);
}

Action::Action(const QCString& name, int accel)
	: name_(name), accel_(accel)
{
}

QString Action::translatedName() const
{
	return qApp->translate("ActionManager", name_);
}

ActionManager::ActionManager()
	: nullAction_("", -1)
{
	for (const ActionDecl *a = actionDecls_; a->id >= 0; ++a) {
		Action action(a->name, 0xF000 + a->id);
		actionMap_.insert(a->name, action);
	}

	createDefaultHotKeyMap();
}

ActionManager &ActionManager::singleton()
{
	static ActionManager actionManager;

	return actionManager;
}

const Action& ActionManager::actionByName(const QCString& name) const
{
	ActionMap::ConstIterator it = actionMap_.find(name);
	if (it == actionMap_.end()) {
		qFatal("ActionManager::actionByName: Illegal action <%s>", static_cast<const char *>(name));
		return nullAction_;
	}
	return it.data();
}

const Action& ActionManager::actionByAccel(int accel) const
{
	ActionMap::ConstIterator it = actionMap_.begin();
	for (; it != actionMap_.end(); ++it) {
		if (it.data().accel() == accel) {
			return it.data();
		}
	}
	qFatal("ActionManager::actionByAccel: Illegal accel <0x%08x>", accel);
	return nullAction_;
}

/*!
  アクションは actionDecls_ で定義された順番に並びます。
 */
QList<Action> ActionManager::allActions() const
{
	QList<Action> l;
	for (const ActionDecl *a = actionDecls_; a->id >= 0; ++a) {
		l.append(&actionByName(a->name));
	}
	return l;
}

/*!
  コンテキスト \a context でのデフォルトの HotKeyMap を返します。
 */
Configuration::HotKeyMap ActionManager::defaultHotKey(Configuration::HotKeyContext context) const
{
	return defaultHotKeyMap_[context];
}

void ActionManager::addHotKey(const QCString &name, int key, int c1,
				   int c2,
				   int c3,
				   int c4)
{
	const Action& action(actionByName(name));

	if (c1 != Configuration::HOTKEY_CONTEXT_MAX)
		defaultHotKeyMap_[c1].insert(key, action.accel());
	if (c2 != Configuration::HOTKEY_CONTEXT_MAX)
		defaultHotKeyMap_[c2].insert(key, action.accel());
	if (c3 != Configuration::HOTKEY_CONTEXT_MAX)
		defaultHotKeyMap_[c3].insert(key, action.accel());
	if (c4 != Configuration::HOTKEY_CONTEXT_MAX)
		defaultHotKeyMap_[c4].insert(key, action.accel());
}
