/**
 *
 * Module:	Initial hwinfo
 *
 * Author:	Ladislav Slezak <lslezak@suse.cz>
 *
 * $Id: inst_hwinfo.ycp 20382 2004-11-23 14:38:47Z lslezak $
 *
 * Initial hwinfo module - configuration workflow
 */

{

textdomain "tune";

import "InitHWinfo";
import "Wizard";
import "Label";
import "Report";
import "Popup";
import "Sequencer";
import "Stage";
import "Arch";

include "hwinfo/routines.ycp";
include "hwinfo/classnames.ycp";
include "hwinfo/newid.ycp";

string selected_model = "";
map selected_info = $[];
string selected_device = nil;


/**
 * Show floppy selection dialog.
 * @param devices map with pairs $["device name" : "model (description)"]
 * @return string selected floppy device name or nil when canceled
 */
define string floppy_selection(map<string,string> devices) ``{
    list devs = maplist(string d, string m, devices, ``{
	    return `item(`id(d), sformat("%1 (%2)", m, d));
	}
    );

    term dialog = `VBox(
	// combo box label
	`ComboBox(`id(`device), _("Select &Floppy Disk Device"), devs),
	`VSpacing(1),
	`HBox(
	    `PushButton(`id(`ok), Label::OKButton()),
	    `VSpacing(2),
	    `PushButton(`id(`cancel), Label::CancelButton())
	)
    );

    symbol ui = nil;

    UI::OpenDialog(dialog);

    while (ui != `ok && ui != `cancel && ui != `close)
    {
	ui = (symbol)UI::UserInput();
    }

    // get selected device
    string selected = (string)UI::QueryWidget(`device, `Value);

    UI::CloseDialog();

    // return nil if [OK] wasn't pressed
    return (ui == `ok) ? selected : nil;
}

/**
 * Select floppy device where hwifo will be stored.
 * If more than one floppy device was found display
 * selection dialog
 * @return string floppy device name (e.g. /dev/fd0) or nil when no floppy was found
 */
define string selected_floppy() ``{

    integer floppy_size = size(InitHWinfo::floppy);

    if (floppy_size == 0)
    {
	return nil;
    }
    else if (floppy_size == 1)
    {
	string device = "";

	// get device name
	foreach(string dev, string m, InitHWinfo::floppy, ``{
		device = dev;
	    }
	);
	return device;
    }
    else
    {
	// there is more than 2 floppies in the system
	// ask user which should be used
	return floppy_selection(InitHWinfo::floppy);
    }
}

/**
 * Show detail dialog for selected device
 * @param model hardware description (used in the tree widget
 * as a root node)
 * @param info hardware description returned by .probe agent
 * @return symbol UserInput() value
 */
define symbol details_dialog(string model, map info) ``{
    // convert information in the map to tree widget content
    list l = [`item(model, true, expandTree(info))];

    term content = `VBox(
	// tree widget label
	`Tree(_("&Details"), l)
    );

    Wizard::HideBackButton();
    Wizard::HideAbortButton();
    Wizard::SetNextButton( `ok, Label::OKButton() );

    // help text
    string help_text = _("<P><B>Details</B></P><P>The details of the selected hardware component are displayed here.</P>");

    // heading text, %1 is component name (e.g. "USB UHCI Root Hub")
    Wizard::SetContents(sformat(_("Component '%1'"), model), content,
			help_text,
			true, true);
    if ( Stage::initial() )
	Wizard::SetTitleIcon( "hardware_info" );

    y2debug("tree content: %1", l);

    symbol ret = `dummy;
    while (ret != `ok && ret != `close)
    {
	ret = (symbol)UI::UserInput();
    }

    if (ret == `close)
    {
	ret = `bort;
    }

    Wizard::RestoreNextButton();
    Wizard::RestoreAbortButton();
    Wizard::RestoreBackButton();

    return ret;
}

/**
 * Show summary dialog with all detected hardware
 * @return symbol UserInput() value
 */
define symbol detected_dialog() ``{

    // this block is evaluated before each hardware class detection
    block<boolean> abortblock = ``{return (UI::PollInput() == `abort && Popup::ReallyAbort(false));};

    list<map> hw = InitHWinfo::DetectedHardware(false, abortblock);

    if (hw == nil)
    {
	// detection was aborted
	return `abort;
    }

    // create table content
    list table_cont = [];

    if (size(hw) > 0)
    {
	foreach(map info, hw, ``{
		// device model name fallback
		string model = (string)(info["model"]:_("Unknown device"));

		string uniq = (string)(info["info", "unique_key"]:"unknown");
		integer class = (integer)(info["info", "class_id"]:0xff);
		integer subclass = (integer)(info["info", "sub_class_id"]:0);

		// find subclass name
		string cls = (string)(ClassNames[class, subclass]:nil);

		// try to use class name if subclass name wasn't found
		if (cls == nil)
		{
		    cls = (string)(ClassNames[class, "name"]:nil);
		}

		// set to "unknown" if class name wasn't found too
		if (cls == nil)
		{
		    // device class is unknown
		    cls = _("Unknown Device Class");
		}

		table_cont = add(table_cont, `item(`id(uniq), cls, model));
	    }
	);
    }

    y2debug("table content: %1", table_cont);

    term content = `VBox(
	// table header
	`Table(`id(`hwtable), `header(_("Class"), _("Model")), table_cont),
	`VSpacing(0.4),
	`HBox(
	    // push button label
	    `PushButton(`id(`newid), _("&Set PCI ID...")),
	    // push button label
	    `PushButton(`id(`details), _("&Details...")),
	    (!Arch::is_uml()) ?
	    // menu button label
	    `MenuButton(`id(`savemenu), _("&Save to File"),
		[
		    // menu item
		    `item(`id(`file), _("Save to &File...")),
		    // menu item
		    `item(`id(`floppy), _("Save to F&loppy..."))
		]
	    )
	    : `Empty()
	),
	`VSpacing(1)
    );

    // help text - part 1/3
    string help_text = _("<P><B>Detected Hardware</B><BR>This table contains all hardware components detected in your system.</P>")
    // help text - part 2/3
    + _("<P><B>Details</B><BR>Select some component and press <B>Details...</B> to see a more detailed description of the component.</P>")
    // help text - part 3/3
    + ((Arch::is_uml()) ? "" : _("<P><B>Save to File</B><BR>You can save hardware information (<I>hwinfo</I> output) to file or to floppy disk. Select the target type in the <B>Save to File</B> menu.</P>"));

    Wizard::HideBackButton();
    Wizard::HideAbortButton();
    Wizard::SetNextButton( `ok, Label::OKButton() );

    // heading text
    Wizard::SetContents(_("Detected Hardware"), content,
			help_text,
			true, true);

    // preselect last selected device
    if (selected_device != nil)
    {
	UI::ChangeWidget(`id(`hwtable), `CurrentItem, selected_device);
    }

    symbol ret = `dummy;

    while (ret != `ok && ret != `details && ret != `newid)
    {
	ret = (symbol)UI::UserInput();

	y2debug("UserInput: %1", ret);

	if (ret == `details || ret == `hwtable)
	{
	    selected_device = (string)(UI::QueryWidget(`id(`hwtable), `CurrentItem));

	    if (selected_device != nil)
	    {
		map device_info = find(map<any,any> i, hw, ``((string)(i["info", "unique_key"]:nil) == selected_device));

		if (device_info != nil)
		{
		    // remember selected device
		    selected_info =  (map)(device_info["info"]:$[]);
		    // device model is unknown
		    selected_model = (string)(device_info["model"]:_("Unknown device"));
		}
		else
		{
		    ret = `dummy;
		}
	    }
	    else
	    {
		ret = `dummy;
	    }
	}
	else if (ret == `floppy)
	{
	    string save_device = selected_floppy();

	    if (save_device != nil)
	    {
		y2debug("Selected floppy: %1", save_device);

		// mount floppy
		string mpoint = mount_device(save_device);

		if (mpoint != nil)
		{
		    save_hwinfo_to_file(mpoint + "/hwinfo.out");

		    // unmount floppy
		    umount_device(mpoint);
		}
		else
		{
		    // error popup - mount failed, %1 is device file name (e.g. /dev/fd0)
		    Report::Error(sformat(_("Floppy device '%1' cannot be mounted."), save_device));
		}

	    }
	}
	else if (ret == `file)
	{
	    // save to file
	    save_hwinfo_to_file("/hwinfo.out");
	}
    }

    Wizard::RestoreNextButton();
    Wizard::RestoreAbortButton();
    Wizard::RestoreBackButton();

    y2debug("detected_dialog result: %1", ret);

    return ret;
}

/**************************************
 *
 *            Main part
 *
 **************************************/

// aliases for wizard sequncer
map aliases =
    $[
	"detected"	:   ``(detected_dialog()),
	"details"	:   [``(details_dialog(selected_model, selected_info)), true],
	"newid"		:   [``(NewIDConfigDialog()), true]
    ];

// workflow sequence
map sequence = $[
    "ws_start" : "detected",
    "detected" :
    $[
	`abort	: `abort,
	// return `abort even when module was correctly finished
	// (avoids restarting installation proposal of all other modules
	//  which doesn't make sense - InitHWinfo is read only module)
	`ok	: `abort,
	`details	: "details",
	`newid : "newid"
    ],
    "details" :
    $[
	`abort	: `abort,
	`ok	: "detected"
    ],
    "newid" :
    $[
	`abort	: `abort,
	`next	: "detected"
    ]
];

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

// start workflow
any ret = Sequencer::Run(aliases, sequence);

Wizard::CloseDialog();

return ret;

}

