/**
 * File:	include/sound/wizards.ycp
 * Package:	Configuration of sound cards
 * Summary:	Wizards definitions
 * Authors:	Dan Vesely <dan@suse.cz>,
 *		Dan Meszaros <dmeszar@suse.cz>,
 *		Jiri Suchomel <jsuchome@suse.cz>
 *
 * $Id: wizards.ycp 22358 2005-03-07 17:01:55Z lslezak $
 */

{

    textdomain "sound";

    import "Mode";
    import "Popup";
    import "Sequencer";
    import "Wizard";
    import "Sound";
    import "Joystick";

    include "sound/card_wizard.ycp";
    include "sound/read_routines.ycp";
    include "sound/routines.ycp";
    include "sound/volume_routines.ycp";
    include "sound/write_routines.ycp";
    include "sound/volume.ycp";
    include "sound/options.ycp";
    include "sound/complex.ycp";
    include "sound/select.ycp";
    include "sound/manual.ycp";


    boolean was_complex = false;

    /**
     * card selection dialog
     * @return symbol next dialog
     */
    define symbol _snd_select() ``{

	Sound::UpdateUnconfiguredCards();
	if ((size(Sound::unconfigured_cards) == 0) && (!was_complex))
	{
	    return `detail;
	}

	list nh	= maplist (map e, Sound::unconfigured_cards, ``(e["model"]:""));
        list ch	= maplist (map e, Sound::modules_conf, ``(e["model"]:""));

	map res		= sound_select (nh, Sound::modules_conf);
	symbol ui	= res["ui"]:`abort;

	Sound::card_id	= res["id"]:0;
	if (Sound::card_id == -1)
	{
	    return `manual;
	}
	return res["ui"]:`abort;
    }

    /**
     * quick configuration step #1 dialog
     * @return symbol next dialog
     */
    define symbol _snd_quick() ``{
	Sound::save_entry	= Sound::unconfigured_cards[0]:$[];
	Sound::card_id	= 0;
	boolean has_joy = false;
	string modname	= Sound::save_entry["module"]:"";
	if (Sound::db_modules [modname, "joystick"]:$[] != $[])
	{
	    has_joy = true;
	}

	string model	= Sound::save_entry["model"]:"";
	map res	= quickConfig (model, "snd-card-0", Sound::card_id, has_joy);

	symbol ui = res["ui"]:`back;
	if (ui == `quick || ui == `normal)
	    Thinkpad600E_cs4236_hack (0);

	return ui;
    }

    /**
     * quick config step #2 dialog
     * @param type boolean quick/normal config
     * @return symbol next dialog
     */
    define symbol _snd_quick2(boolean type) ``{
	Sound::save_entry  = add_common_options(Sound::save_entry, 0);
	Sound::save_entry  = add_alias(Sound::save_entry, 0);
	map res	    = sound_volume(Sound::save_entry, 0, true, type, []);
	symbol ui	= res["ui"]:`back;
	if (ui == `next)
	{
	    Sound::modules_conf = [Sound::save_entry];
	}
	return ui;
    }


    /**
     * dialog for manual card selection
     * @return symbol next dialog
     */
    define symbol _snd_manual() ``{

	map res		= sound_manual();
	symbol ui	= res["ui"]:`abort;

	if (ui == `next)
	{
	    Sound::save_entry		= update_manual_card (res);
	    Sound::card_id	= -1;
	}
	if (ui == `back)
	{
	    Sound::save_entry	= $[];
	}
	return ui;
    }

    /**
     * add card from complex dialog
     * @return symbol next dialog
     */
    define symbol _snd_add() ``{
	list<string> nh	= maplist (map card, Sound::unconfigured_cards, ``(
	    card["model"]:""));

	map res		= WhichDialog(nh);
	symbol ui	= res["ui"]:`back;
        Sound::card_id	= res["card_id"]:-1;

        if (Sound::card_id == -1 && ui == `next)
        {
            return `manual;
        }
	return ui;
    }

    /**
     * sound card deletion
     * @return symbol next dialog
     */
    define symbol _snd_delete() ``{
	if (!Sound::use_ui ||
	    // popup question
	    Popup::YesNo(_("Do you really want to delete this entry?")))
	{
	    if (!stop_programs())
            {
                return `next;
            }

	    // remove joystick settings
	    if (Sound::card_id<4 && Joystick::joystick[Sound::card_id]:nil!=nil)
	    {
		Joystick::joystick = remove (Joystick::joystick,Sound::card_id);
		Joystick::joystick[3] = $[];
	    }

            // we have to remember volume/mute settings because after a
	    // card removal everything is muted and set to 0.
            list vol_settings = get_vol_settings();
	    if (Mode::config())
		vol_settings	= Sound::volume_settings;

            Sound::modules_conf	= remove (Sound::modules_conf, Sound::card_id);
	    Sound::modules_conf	    = recalc_save_entries(Sound::modules_conf);

	    // remember info about removed card
	    map removed_card = Sound::detected_cards[Sound::card_id]:$[];

	    if (size(removed_card) > 0)
	    {
		map removed_info = $[];

		removed_info["bus_hwcfg"] = removed_card["bus_hwcfg"]:"";
		removed_info["sysfs_bus_id"] = removed_card["sysfs_bus_id"]:"";
		removed_info["unique_key"] = removed_card["unique_key"]:"";

		if (!contains(Sound::removed_info, removed_info))
		{
		    Sound::removed_info = add(Sound::removed_info, removed_info);
		    y2milestone("added removed card info: %1", removed_info);
		}
	    }

	    if (vol_settings[Sound::card_id]:nil != nil)
	    {
		vol_settings    = remove (vol_settings, Sound::card_id);
		// we have to move old entry in global list:
		if (!Mode::config())
		    Sound::volume_settings = add (vol_settings,
			Sound::volume_settings[Sound::card_id]:[]);
		else
		    Sound::volume_settings = eval (vol_settings);
	    }

	    if (!Mode::config())
	    {
		sound_stop();
		sound_start_tmp(true);
		set_vol_settings(vol_settings);
		// now we have to update the unconfigured cards list
		Sound::UpdateUnconfiguredCards();
	    }
	}
	return `next;
    }

    /**
     * configure selected card
     * @return symbol next dialog
     */
    define symbol _snd_config() ``{
	if (Sound::card_id >= 0)
	{
	    Sound::save_entry = Sound::unconfigured_cards [Sound::card_id]:$[];
	}
	map res = OneCardWizard (Sound::save_entry, size(Sound::modules_conf),
	    15, false, Sound::modules_conf);

	symbol ui	= res["ui"]:`back;
        if (ui == `next)
        {
	    // copy card_entry from unconfigured to configured list
            Sound::modules_conf = add(Sound::modules_conf, res["return"]:$[]);
	    if (Sound::card_id >= 0)
	    {
		// if this this card was autodetedted, remove
		// card we've just configured from unconfigured card list.
		Sound::unconfigured_cards = remove (Sound::unconfigured_cards,
		    Sound::card_id);
	    }
	    if (size(Sound::unconfigured_cards) == 0)
	    {
		// no other detected && unconfigured cards remained
		return `detail;
	    }
        }
	return ui;
    }

    /**
     * complex dialog
     * @return symbol next dialog
     */
    define symbol _snd_complex() ``{
	was_complex = true;
	map res	    = sound_complex();
        return (symbol) (res["ui"]:nil);
    }


/**
 * Main workflow of sound configuration (without read and write)
 * @return sequence result
 */
define symbol MainSequence(string initial) ``{

    map m_aliases = $[
	    "intro"	: ``(_snd_select()),

	    "config1"	: ``(_snd_config()),
	    "config2"	: ``(_snd_config()),

	    "manual1"	: ``(_snd_manual()),
	    "manual2"	: ``(_snd_manual()),

	    "complex"	: ``(_snd_complex()),
	    "delete"	: ``(_snd_delete()),
	    "select"	: ``(_snd_add()),

	    // quick configuration
	    "quick"	: ``(_snd_quick()),
	    "quick2"	: ``(_snd_quick2(true)),
	    "quick3"	: ``(_snd_quick2(false)),
	];

    map m_sequence = $[
	    "ws_start"	: initial,
	    "quick"	:
		$[
		    `quick	    :	"quick2",
		    `normal	    :	"quick3",
		    `abort	    :	`abort,
		    `intro	    :	"intro"
		],
	    "quick2"	:
		$[
		    `next	    :	`finish,
		    `abort	    :	`abort
		],
	    "quick3"	:
		$[
		    `next	    :	`finish,
		    `abort	    :	`abort
		],

	    "intro"	:
		$[
		    `next	    :	`finish,
		    `configure	    :   "config1",
		    `manual	    :	"manual1",
		    `detail	    :	"complex",
		    `abort	    :	`abort
		],

	    "config1"	:
		$[
		    `next	    :	"intro",
		    `detail	    :	"intro",
		    `abort	    :   `abort
		],
	    "manual1"	:
		$[
		    `next	    :	"config1",
		    `abort	    :	`abort
		],

	    "config2"	:
		$[
		    `next	    :	"complex",
		    `detail	    :	"complex",
		    `abort	    :   `abort
		],
	    "manual2"	:
		$[
		    `next	    :	"config2",
		    `abort	    :	`abort
		],

	    "complex"	:
		$[
		    `next	    :	`finish,
		    `abort	    :	`abort,
		    `add_manual     :	"manual2",
		    `add_select	    :	"select",
		    `delete	    :	"delete"
		],
	    "select"	:
		$[
		    `abort	    :	`abort,
		    `next	    :	"config2",
		    `manual	    :	"manual2"
		],
	    "delete"	:
		$[
		    `next	    :	"complex"
		],
    ];

    return Sequencer::Run (m_aliases, m_sequence);
}

// TODO create AutoSequence (used also for installation?)
// - call of MainSequence with some work before and after

/**
 * Whole configuration of sound
 * @return sequence result
 */
define symbol SoundSequence () ``{

    Sound::use_ui = true;

    Wizard::CreateDialog();
    Wizard::SetDesktopIcon("sound");

    if (!Mode::config() && !Sound::installation)
    {
	if (!Sound::Read(true))
	    return `abort;
	block<boolean> abort = ``{ return false;};
	Joystick::Read(abort);
	Sound::StoreSettings();
    }

    if (Sound::installation)
    {
	Sound::StoreSettings();
	if (Sound::detected_cards == [] && Sound::modules_conf == [])
	    Sound::DetectOldCards();
	Sound::UpdateUnconfiguredCards();
	sound_stop();
	sound_start_tmp(true);
	// init mixer for all soundcards
	integer index = 0;
	maplist (map card, Sound::modules_conf, ``{
	    Sound::InitMixer(index, card["module"]:"");
	    index = index + 1;
	});
    }

    integer n_cards	= 0;
    integer all_cards_num = size(Sound::unconfigured_cards);

    nm256_opl3sa2_warn (flatten(
	add([Sound::modules_conf], Sound::unconfigured_cards)));

    if (size(flatten(add([Sound::modules_conf], Sound::unconfigured_cards)))==1)
    {
	boolean nm256out = nm256hack (Sound::unconfigured_cards[0,"module"]:"");
	y2debug("continue configuring: %1", nm256out);
	if (!nm256out)
	{
	    UI::CloseDialog();
	    return `back;
	}
    }
    string initial = "intro";

    // when running this module as non-root, go to complex-dialog
    if (size(Sound::unconfigured_cards) == 1 && size(Sound::modules_conf) == 0)
    {
	Sound::card_id = 0;
	initial = "quick";
    }
    else if (size(Sound::unconfigured_cards) == 0)
    {
	initial = "complex";
    }

    symbol ui = MainSequence (initial);

    if (ui == `back || ui == `abort)
    {
	if (Sound::installation)
	{
	    Sound::RestoreSettings();
	}
	UI::CloseDialog();
	return `back;
    }

    n_cards = size (Sound::modules_conf);

    map save_map = $[];

    if (Sound::installation)
    {
	if (ui != `finish)
	{
	    Sound::RestoreSettings();
	}
	else
	    ui = `next; // in installation mode, `finish is end of installation
    }

    if (ui == `finish && !Mode::config())
    {
	if (!Sound::installation && ( Sound::Changed() || Joystick::Changed()))
	{
	    Sound::Write ();
	}
    }

    UI::CloseDialog ();
    return ui;
}

/* EOF */
}
