/**
 * File:	clients/hwinfo.ycp
 * Module:	Hardware information
 * Summary:	Main file
 * Authors:	Dan Meszaros <dmeszar@suse.cz>
 *		Ladislav Slezak <lslezak@suse.cz>
 *		Michal Svec <msvec@suse.cz>
 *
 * $Id: hwinfo.ycp 20382 2004-11-23 14:38:47Z lslezak $
 */

{

textdomain "tune";
import "Wizard";
import "Label";
import "Arch";

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

/**
 * this global variable is needed for skipping out from recursed function
 */
boolean abortPressed = false;

/*
 * open progress bar window
 */
UI::OpenDialog(
    `HBox(
	`VSpacing(7),
	`VBox(
	    `HSpacing(40),
	    // popup dialog header
	    `Label(_("Probing:")),
	    `HBox(
		`HWeight(1, `Label(`id(`initLab), ""))
	    ),
	    // progress bar label
	    `ProgressBar(`id(`initProg), _("Progress:"), 1000, 0),
	    `VSpacing(0.5),
	    `PushButton(`id(`abort), `opt(`key_F9), Label::AbortButton())
	)
    )
);

/*
 * these paths will be excluded from probing.
 * .probe.mouse doesn't like running X
 * other paths are not user-interesting
 */
list exclude_list = [.probe.byclass, .probe.bybus, .probe.ihw_data, .probe.system, .probe.status, .probe.cdb_isdn, .probe.boot_disk];

if (Arch::is_uml())
{
    // exclude more path in UML system, UML supports/emulates only few devices
    exclude_list = union(exclude_list, [ .probe.scsi, .probe.camera, .probe.pppoe, .probe.isapnp, .probe.tape, .probe.joystick,
	.probe.usb, .probe.ieee1394ctrl, .probe.usbctrl, .probe.cdrom, .probe.floppy, .probe.chipcard, .probe.mouse
    ]);
}

/*
 * if xserver is running, don't probe for mouse and chipcard
 * because it has bad side effect (moving cursor)
 */
if (SCR::Execute(.target.bash, "/bin/ps -C X") == 0)
{
    y2warning("X server is running - mouse and chipcard will not be probed");
    exclude_list = add(exclude_list, .probe.mouse);

    // .probe.chipcard has same effect as .probe.mouse
    exclude_list = add(exclude_list, .probe.chipcard);
}


/**
 * Add extra CPU info from .proc.cpuinfo to data read from .probe agent
 * @param cpuinfo CPU information returned by .probe agent
 * @return list input with additional CPU information
 */

define list add_cpu_info(list<map> cpuinfo) ``{
    // add information from /proc/cpuinfo for each CPU
    integer cpu_index = 0;

    list ret = maplist(map probe_cpuinfo, cpuinfo, ``{
	    // get all keys for selected processor
	    list<string> keys = (list<string>) SCR::Dir(add(.proc.cpuinfo.value, sformat("%1", cpu_index)));

	    if (keys != nil)
	    {
		// read values
		foreach(string key, keys, ``{
			probe_cpuinfo = add(probe_cpuinfo, key, SCR::Read(add(add(.proc.cpuinfo.value, sformat("%1", cpu_index)), key)));
		    }
		);

		// add processor index
		probe_cpuinfo = add(probe_cpuinfo, "Processor", cpu_index);
	    }

	    cpu_index = cpu_index + 1;

	    return probe_cpuinfo;
	}
    );

    return ret;
}

/**
 * returns string that is behind the last dot of given string (extract last part of path)
 * @param str path in string form
 * @return string last path element
 */

define string afterLast(string str) ``{
    list strs = splitstring(str, ".");
    return strs[size(strs) - 1]:"";
}

/**
 * Returns list of values read from path p
 * @param progMin minimum value used in progressbar
 * @param progMax maximum value used in progressbar
 * @param p read path p
 * @return term tree widget content
 */

define term buildHwTree(string p, integer progMin, integer progMax) ``{

    y2debug("buildHwTree path: %1", p);

    any a = UI::PollInput();
    if (a == `cancel || a == `abort)
    {
	abortPressed = true;
	return nil;
    }

    UI::ChangeWidget(`id(`initLab), `Value, trans_str(afterLast(p)));
    path pat = topath(p);

    y2debug("Reading path: %1", p);

    if (contains(exclude_list, pat))
    {
	return nil;
    }

    list<string> dir = (list<string>) SCR::Dir(pat);

    if (dir == nil)
    {
	any val = SCR::Read(pat);

	if (scalar(val))
	{
	    return `item(sformat("%1: %2", trans_str(afterLast(p)), trans_bool(val)));
	}
	else if (val == nil ||  val == [] || val == $[])
	{
	    return nil;
	}
	else
	{
	    if (afterLast(p) == "cpu")
	    {
		val = add_cpu_info((list<map>) val);
	    }
	    return `item(trans_str(afterLast(p)), expandTree(val));
	}
    }
    else
    {

	// remove duplicates from the list
	list<string> uniq = [];

	foreach(string d, dir, ``{
		if (!contains(uniq, d))
		{
		    uniq = add(uniq, d);
		}
	    }
	);

	dir = uniq;

	integer step=1000;
	if (size(dir)!=0)
	{
	    step = (progMax - progMin) / size(dir);
	}
	integer prog = progMin;

	integer pos = size(dir)-1;
	list    lout = [];
	term    itm = nil;
	while(pos >= 0)
	{
	    itm = buildHwTree(p + "." + dir[pos]:nil, prog, prog + step);
	    if (abortPressed)
	    {
		return nil;
	    }
	    if (itm != nil)
	    {
		lout = add(lout, itm);
	    }
	    pos = pos - 1;
	    prog = prog + step;
	    UI::ChangeWidget(`id(`initProg), `Value, prog);
	}
	return `item(afterLast(p), sort(lout));
    }
    return nil;
}


// Main

// tree item list
term items = nil;
// default initial path
path pat = .probe;
if (size(WFM::Args()) > 0)
{
    // initial path overriden by module argument
    pat = topath(WFM::Args(0));
}

// build the tree
items = buildHwTree(sformat("%1", pat), 0, 1000);

// interrupted
if (abortPressed)
{
    UI::CloseDialog();
    return `abort;
}

// title label
string title = _("&All Entries"); //this wasn't marked for translation in 8.0
if(pat != .probe)
{
    title = trans_str(afterLast(sformat("%1", pat)));
}

UI::CloseDialog();

term con = `Tree(`id(`idTree), `opt(`vstretch, `hstretch), title, items[1]:nil);

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


Wizard::SetBackButton(`save, _("&Save to File...") );
Wizard::SetNextButton(`next, Label::CloseButton() );

// abort is not needed, module is read-only
Wizard::HideAbortButton();


// dialog header
Wizard::SetContents (_("Hardware info"), con,

// help text
 _("<P>The <B>Hardware Information</B> module displays the hardware
details of your computer. Click any node for more information.</p>\n")
+ _("<P>You can save hardware information to a file. Click <B>Save to File</B> and enter the file name.</P>"),
true, true);

UI::SetFocus(`id(`idTree));

any event = nil;

// wait for finish
while(event != `abort && event !=`next && event != `cancel)
{
    event = UI::UserInput();

    if (event == `save)
    {
	// store hwinfo output to the file
	save_hwinfo_to_file("/");
    }
}
Wizard::CloseDialog();
return `next;

/* EOF */
}
