/**
 * File:	modules/Joystick.ycp
 * Package:	Joustick configuration
 * Summary:	Joystick data
 * Authors:	Ladislav Slezak <lslezak@suse.cz>
 *
 * $Id: Joystick.ycp 19990 2004-10-27 10:25:26Z lslezak $
 */

{

    module "Joystick";
    textdomain "sound";

    import "Mode";
    import "Service";

    /**
     * joystick config datastructure (list of maps)
     */
    global list joystick = [];

    list<string> vars = [   "GAMEPORT_MODULE",
                    "JOYSTICK_MODULE",
                    "JOYSTICK_MODULE_OPTION",
                    "JOYSTICK_CONTROL",
                    "JOYSTICK_CONTROL_PORT"];

    list joystick_backup = [];

    global string start = "";

    global boolean modified = false;

    // comment for JOYSTICK_MODULE section in sysconfig
    string module_comment = "";

    global string generic_joystick = "Generic Analog Joystick";
    // database entry
    global string generic_joystick_translated = _("Generic Analog Joystick");

    /**
     * Get list of all required joystick kernel modules
     * @return list list of modules
     */
    global define list<string> RequiredKernelModules() {
	list<string> ret = [];

	foreach(map j, (list<map>)joystick, {
		string gport = j["GAMEPORT_MODULE"]:"";
		string jmod = j["JOYSTICK_MODULE"]:"";

		if (gport != nil && gport != "")
		{
		    ret = add(ret, gport);
		}

		if (jmod != nil && jmod != "")
		{
		    ret = add(ret, jmod);
		}
	    }
	);

	// remove duplicates
	ret = toset(ret);

	y2milestone("Required joystick modules: %1", ret);

	return ret;
    }

    /**
     * Read all joystick settings from the SCR
     * @param abort A block that can be called by Read to find
     *	      out whether abort is requested. Returns true if abort
     *	      was pressed.
     * @return True on success
     */
    global define boolean Read (block<boolean> abort) ``{

	// values for test mode
	if (Mode::test() == true)
	{
	    joystick = [$["GAMEPORT_MODULE":"ns558", "JOYSTICK_CONTROL":"Joystick", "JOYSTICK_CONTROL_PORT":"", "JOYSTICK_MODULE":"analog", "JOYSTICK_MODULE_OPTION":"", "model":"Generic Analog Joystick"], $["GAMEPORT_MODULE":"", "JOYSTICK_CONTROL":"", "JOYSTICK_CONTROL_PORT":"", "JOYSTICK_MODULE":"", "JOYSTICK_MODULE_OPTION":"", "model":""], $["GAMEPORT_MODULE":"", "JOYSTICK_CONTROL":"", "JOYSTICK_CONTROL_PORT":"", "JOYSTICK_MODULE":"", "JOYSTICK_MODULE_OPTION":"", "model":""], $["GAMEPORT_MODULE":"", "JOYSTICK_CONTROL":"", "JOYSTICK_CONTROL_PORT":"", "JOYSTICK_MODULE":"", "JOYSTICK_MODULE_OPTION":"", "model":""]];
	    joystick_backup = joystick;

	    return true;
	}

	integer pos = 0;

	joystick = [];

	while (pos < 4)
	{
	    map j = $[];

	    // go thru 'vars' list and read all variable values
	    foreach(string v, vars, ``{
		string tmp = (string) SCR::Read (
		    topath(sformat(".sysconfig.joystick.%1_%2", v, pos)));
		if (tmp != nil)
		    j = add(j, v, tmp);
	    });

	    // read model comment
	    string model = (string) SCR::Read(topath(
		sformat(".sysconfig.joystick.JOYSTICK_MODULE_%1.comment",pos)));

	    y2debug("Read model comment: %1", model);

	    // remove trailing newline character
	    if (size(model) > 0 && substring(model, size(model) - 1, 1) == "\n")
	    {
		model = substring(model, 0, size(model) - 1);
	    }

	    // if comment has more lines get last line as model name
	    list<string> lines = splitstring(model, "\n");

	    // select last line from comment
	    if (size(lines) > 1)
	    {
		model = lines [ size(lines) - 1 ]:"";

		// store global comment for joystick modules -
		// - it is before first module
		if (pos == 0)
		{
		    lines = remove(lines, size(lines) - 1);
		    module_comment = mergestring(lines, "\n");

		    y2debug("global comment: %1", module_comment);
		}
	    }

	    // set model
	    if (SCR::Read(topath(
		    sformat(".sysconfig.joystick.JOYSTICK_MODULE_%1", pos)))==""
		|| model == nil)
	    {
		model = "";
	    }
	    else
	    {
		// remove comment char
		if (substring(model, 0, 1) == "#")
		{
                    if (size(model) > 1)
		    {
			model = substring(model, 1);
		    }
		    else
		    {
			model = "";
		    }
		}

		// remove new line char
		if (size(model) > 1 &&
		    substring(model, size(model) - 1, 1) == "\n")
		{
		    model = substring(model, 0, size(model) - 1);
		}
	    }

	    j = add(j, "model", model);

	    joystick = add(joystick, j);

	    pos = pos + 1;
	}

	joystick_backup = joystick;
	return true;
    }

    /**
     * Return configuration status
     * @return true if configuration was changed
     */
    global define boolean Changed() ``{
	return (joystick != joystick_backup);
    }

    /**
     * Update the SCR of the one joystick
     * @param pos joystick number
     */
    global define boolean SaveOneJoystick (integer pos) ``{

	// first remove old settings
	foreach (string v, vars, ``{
	    SCR::Write(topath(sformat(".sysconfig.joystick.%1_%2", v, pos)),"");
	});

	// delete old model
	SCR::Write(topath(
	    sformat(".sysconfig.joystick.JOYSTICK_MODULE_%1.comment", pos)),"");

	map j = joystick[pos]:$[];

	foreach (string v, vars, ``{

	    SCR::Write(topath(sformat(".sysconfig.joystick.%1_%2", v, pos)),
		j[v]:"");

	    if (j[v]:"" != "")
            {
	        // if there is variable with value != "" enable joystick service
	        start = "enable";
            }
	});

	// write model comment
	string model = j["model"]:"";

	// add comment before first model
	if (pos == 0)
	{
	    if (size(model) > 0)
	    {
	        model = module_comment + "\n#" + model + "\n";
	    }
	    else
	    {
	        model = module_comment + "\n#\n";
	    }
	}
	else
	{
	    if (size(model) > 0)
	    {
	        model = "#" + model + "\n";
	    }
	}

	y2debug("Read model comment: %1", model);

	if (size(model) > 0)
	{
	    SCR::Write(topath(
		sformat(".sysconfig.joystick.JOYSTICK_MODULE_%1.comment", pos)),
		model);
	}
	return true;
    }

    /**
     * Stop joystick service
     */
    global define boolean Stop() ``{
	return
	    (SCR::Execute(.target.bash, "/etc/init.d/joystick stop", $[]) == 0);
    }

    /**
     * Write sysconfig values (flush)
     */
    global define boolean WriteConfig() ``{
	return SCR::Write(.sysconfig.joystick, nil);
    }

    /**
     * Start joystick service and insserv it
     */
    global define boolean StartAndEnable() ``{

	if (start == "enable")
	    SCR::Execute(.target.bash, "/etc/init.d/joystick start", $[]);
	Service::Adjust("joystick", start);
	return true;
    }

    /**
     * Update the SCR according to joystick settings
     * @param abort A block that can be called by Write to find
     *	      out whether abort is requested. Returns true if abort
     *	      was pressed.
     * @return True on success
     */
    global define boolean Write (block<boolean> abort) ``{
	// do not write anything in the test mode and if nothing was changed
	if (Mode::test() == true || !modified)
	{
	    return true;
	}

	integer pos = 0;

	start = "disable";

	// stop joystick service
	Stop();

	while (pos < 4)
	{
	    // update /etc/sysconfig/joystick file
	    SaveOneJoystick (pos);
	    pos = pos + 1;
	}

	// flush config to file
	WriteConfig();

	// start joystick service
	// enable/disable service
	StartAndEnable();

	y2milestone("%1", "Joystick configuration was written.");

	return true;
    }

    /**
     * Get all joystick settings from the first parameter
     * (For use by autoinstallation.)
     * @param settings The YCP structure to be imported.
     * @return True on success
     */
    global define boolean Import (list settings) ``{
	joystick = settings;
	return true;
    }

    /**
     * Dump the joystick settings to a single map
     * (For use by autoinstallation.)
     * @return Dumped settings (later acceptable by Import ())
     */
    global define list Export () ``{
	return joystick;
    }

    /**
     * Build a textual summary that can be used e.g. in inst_hw_config () or
     * something similar.
     * @return Summary of the configuration.
     */
    global define string Summary () ``{
	return _("Summary of the joystick configuration...");
    }

/* EOF */
}
