/**
 * File:	clients/inst_do_net_test.ycp
 * Package:	Network configuration
 * Summary:	Configuration dialogs for installation
 * Authors:	Michal Svec <msvec@suse.cz>
 *		Arvin Schnell <arvin@suse.de>
 *
 * $Id: inst_do_net_test.ycp 21789 2005-02-21 15:58:47Z mvidner $
 */

{

textdomain "network";

import "Directory";
import "Internet";
import "Label";
import "Mode";
import "Popup";
import "Product";
import "Wizard";
import "PackageCallbacks";
import "Proxy";
import "GetInstArgs";

include "network/routines.ycp";
include "network/installation/dialogs.ycp";


/* Called backwards */
if(GetInstArgs::going_back())
   return `auto;


if(!Internet::do_test)
    return `auto;

/* Nothing to test */
if(!Internet::FindFastest())
    return `auto;


boolean we_have_patches = false;

// do we have a connection already?
// then don't open or close it, don't show respective steps
boolean already_up = false;

// Stage transitions in handle_stage:
// open: wait (test), copy, finish (failure), wait
// wait: copy (test), finish (failure), copy
// copy: relnotes
// relnotes: patches
// patches: close
// close: finish
// finish
symbol test_stage = `open;

symbol test_result = `success;

// list of all log files to show
list<map> logs = [];

// dir of log files
// Formerly it was under tmpdir and thus got erased automatically.
// Now we want to keep it (#46285), so let's put it under logdir.
string logdir = Directory::logdir + "/internet-test";


if(!Mode::test ())
    already_up = Internet::Status();


/* Progress step 1/4 */
string l1 = _("Connecting to Internet...");
/* Progress step 2/4 */
string l2 = _("Downloading the latest release notes...");
/* Progress step 3/4 */
string l3 = _("Checking for latest updates...");
/* Progress step 4/4 */
string l4 = _("Closing connection...");


/**
 * Return current language with .UTF-8 appended.
 * FIXME: there must be a better way!
 */
define string GetLanguageUTF8 ()
{
    string tmp = WFM::GetLanguage ();
    integer pos = findfirstof (tmp, "@.");
    if (pos != nil)
	tmp = substring (tmp, 0, pos);
    return tmp + ".UTF-8";
};


/* fix checkycp complaints */
string dash = "-   ";

    /**
     * Create the dialog contents
     */
    define void make_dialog ()
    {
	/* Test dialog caption */
	string caption = _("Running Internet Connection Test");

	/* help for dialog "Running Internet Connection Test" */
	string help = _("<p>Here, view the progress of the
Internet connection test.</p>
") +

	    /* help for dialog "Running Internet Connection Test" */
	    _("<p>The test can be aborted by pressing
<b>Abort Test</b>.</p>
");

	// In update mode there's no network setup, #50381
	// Actually it depends on the control file, but it's only a help text
	if (!Mode::update ())
	{
	    help = help +
		/* help for dialog "Running Internet Connection Test" */
		_("<p>If the test fails, return to the network configuration
and correct the settings.</p>
");
	}

	/* Progress labels */
	term progress = `VBox();

	if(!already_up)
	    progress = add(progress, `Left(`HBox(`Heading(`id(`s1), dash), `Label(l1))));
	if(true)
	    progress = add(progress, `Left(`HBox(`Heading(`id(`s2), dash), `Label(l2))));
	if(Product::run_you)
	    progress = add(progress, `Left(`HBox(`Heading(`id(`s3), dash), `Label(l3))));
	if(!already_up)
	    progress = add(progress, `Left(`HBox(`Heading(`id(`s4), dash), `Label(l4))));

	progress = add(progress, `VStretch());

	progress = add(progress, `HBox(
				       /* Label for result of internet test */
				       `Label(_("Result:")),
				       `HSpacing(2),
				       `Label(`id(`res), `opt(`outputField, `hstretch), "")
				       ));

	progress = add(progress, `VStretch());

	/* Push Button to abort internet test */
	progress = add(progress, `PushButton(`id(`abort_test), _("&Abort Test")));

	/* Frame label: status of internet test */
	progress = `Frame (_("Test Status"),
			   `VBox (
			       `VSpacing (1),
			       `HBox (
				   `HSpacing (1),
				   progress,
				   `HSpacing (1)
				   ),
			       `VSpacing (1)
			       )
	    );

	/* Test dialog contents */
	term contents = `VBox(
			      `VStretch(),
			      `VBox(`HVCenter(`HSquash(progress))),
			      `VStretch(),
			      /* Push Button to see logs of internet test */
			      `PushButton(`id(`view_log), `opt(`disabled), _("&View Logs...")),
			      `VStretch()
			      );

	Wizard::SetContents(caption, contents, help, true, true);
    }


    /**
     * @param i step number 1..4
     * @param s bullet: `arrow: current, `check: done, `dash: not done or failed
     */
    define void mark_label (integer i, symbol s)
    {
	list<symbol> widgets = [nil, `s1, `s2, `s3, `s4];
	map<symbol, string> bullets = $[
	    `arrow : UI::Glyph (`BulletArrowRight),
	    `check : UI::Glyph (`CheckMark),
//	    `dash :  dash,
	    // preserve the previous look
	    `dash : UI::Glyph (`CheckMark),
	    ];

	UI::ChangeWidget (`id (widgets[i]:nil), `Value, bullets[s]:"?");
    }


    define void show_result ()
    {
	if(test_result == `success) {
	    /* result of internet test */
	    UI::ChangeWidget(`id(`res), `Value, _("Success"));
	} else {
	    /* result of internet test */
	    UI::ChangeWidget(`id(`res), `Value, _("Failure"));
	}
    }


    define void copy_logs1 ()
    {
	// label of combobox where the log is selected
	logs = add (logs, $[ `menuname : _("Kernel Network Interfaces"),
			     `filename : "ifconfig.log" ]);
	SCR::Execute (.target.bash, "/sbin/ifconfig > " +
		      logdir + "/ifconfig.log",
		      $["LANG" : GetLanguageUTF8 ()]);

	// label of combobox where the log is selected
	logs = add (logs, $[ `menuname : _("Kernel Routing Table"),
			     `filename : "route.log" ]);
	SCR::Execute (.target.bash, "/sbin/route -n > " + logdir + "/route.log",
		      $["LANG" : GetLanguageUTF8 ()]);

	// label of combobox where the log is selected
	logs = add (logs, $[ `menuname : _("Host Name Lookup"),
			     `filename : "resolv.conf" ]);
	SCR::Execute (.target.bash, "/bin/cp /etc/resolv.conf " +
		      logdir + "/resolv.conf");
    }


    define void copy_logs2 ()
    {
	// label of combobox where the log is selected
	logs = add (logs, $[ `menuname : _("Kernel Messages"),
			     `filename : "messages" ]);
	SCR::Execute (.target.bash, Directory::ybindir + "/cut-messages > " +
		      logdir + "/messages");

	if (Internet::logfile != "") {
	    // label of combobox where the log is selected
	    logs = add (logs, $[ `menuname : _("PPP Daemon"),
				 `filename : "smpppd.log",
				 `prio : 20 ]);
	    SCR::Execute (.target.bash, "/bin/cp " + Internet::logfile + " " +
			  logdir + "/smpppd.log");
	}
    }


    define boolean download_release_notes (string& filename)
    {
	string url = Product::relnotesurl;

	integer pos = findlastof (url, "/");
	if (pos == nil)
	{
	    y2error ("broken url for release notes: %1", url);
	    return false;
	}

	filename = (string) SCR::Read (.target.tmpdir) + substring (url, pos);

	string cmd = "/usr/bin/curl -s -S -v -f -m 300 " + url + " -o " + filename;
	cmd = cmd + " > " + logdir + "/curl.log 2>&1";

	map env = Proxy::GetEnvironment ();

	env["LANG"] = GetLanguageUTF8 ();

	integer ret = (integer) SCR::Execute (.target.bash, cmd, env);

	y2milestone ("curl command returned %1", ret);

	// label of combobox where the log is selected
	logs = add (logs, $[ `menuname : _("Download of Release Notes"),
			     `filename : "curl.log" ]);

	return ret == 0;
    }


    define boolean install_release_notes (string filename)
    {
	boolean ret1 = Pkg::RpmChecksig (filename);

	if (!ret1)
	{
	    // FIXME: show popup
	    y2error ("checksig of release notes failed");
	    return false;
	}

	boolean old2 = PackageCallbacks::EnableAsterixPackage (false);
	boolean ret2 = Pkg::TargetInstall (filename);
	PackageCallbacks::EnableAsterixPackage (old2);

	if (!ret2)
	{
	    // FIXME: show popup
	    y2error ("installing of release notes failed");
	    return false;
	}

	return true;
    }


    define void handle_stage ()
    {
	if (test_stage == `open)		// open connection
	{
	    if(Mode::test ()) {
		mark_label(1, `arrow);
		test_stage = `wait;
		return;
	    }

	    if(already_up)
	    {
		test_stage = `copy;
	    }
	    else
	    {
		mark_label(1, `arrow);

		if(!AskForPassword()) {
		    y2error("Password required");
		    test_stage = `finish;
		    test_result = `failure;
		    mark_label (1, `dash);
		    return;
		}

		// start the connection
		y2milestone("called Start");
		// label of combobox where the log is selected
		logs = add (logs, $[ `menuname : _("Opening of Connection"),
				     `filename : "ifup.log",
				     `prio : 16 ]);
		if(!Internet::Start(logdir + "/ifup.log")) {
		    // popup to inform user about the failure
		    Popup::Message(_("Connecting to the Internet failed. View
the logs for details.
"));
		    test_stage = `finish;
		    test_result = `failure;
		    mark_label (1, `dash);
		    return;
		}

		test_stage = `wait;
	    }
	    return;
	}

	if (test_stage == `wait)		// wait until really connected
	{
	    if(Mode::test ()) {
		test_stage = `copy;
		mark_label(1, `check);
		return;
	    }

	    // status must be up
	    if(!Internet::Status()) {
		// popup to inform user about the failure
		Popup::Message(_("Connecting to the Internet failed. View
the logs for details.
"));
		test_stage = `finish;
		test_result = `failure;
		mark_label (1, `dash);
		return;
	    }

	    // and we must be connected
	    if(Internet::Connected())
	    {
		y2milestone("Connected ok");
		test_stage = `copy;
		mark_label(1, `check);
		return;
	    }

	    // ping anything (www.suse.com) to trigger dod connections
	    SCR::Execute(.target.bash_background,
			 "/bin/ping -c 1 -w 1 213.95.15.200");
	    return;
	}

	if (test_stage == `copy)		// copy some status
	{
	    copy_logs1 ();
	    test_stage = `relnotes;
	}

	if (test_stage == `relnotes)		// download release notes
	{
	    mark_label(2, `arrow);

	    string filename = "";

	    if (!download_release_notes (filename))
	    {
		// popup to inform user about the failure
		Popup::Message(_("Download of latest release notes failed. View
the logs for details.
"));
		test_stage = `patches;
		test_result = `failure;
		mark_label(2, `dash);
	    }
	    else
	    {
		install_release_notes (filename);
		mark_label(2, `check);
	    }

	    test_stage = `patches;
	    return;
	}

	if (test_stage == `patches)		// check for updates
	{
	    if(!Product::run_you)
	    {
		test_stage = `close;
		return;
	    }

	    mark_label(3, `arrow);

	    string cmd = "/usr/bin/online_update -q -V";
	    // ugly hack (see bug #42177)
	    // string cmd = "/bin/false";
	    cmd = cmd + "> " + logdir + "/you.log 2>&1";
	    integer ret = (integer) SCR::Execute (.target.bash, cmd,
					$["LANG" : GetLanguageUTF8 ()]);
	    y2milestone("online_update command returned %1", ret);

	    // label of combobox where the log is selected
	    logs = add (logs, $[ `menuname : _("Check for Patches"),
				 `filename : "you.log" ]);

	    if(ret == 0 || ret == 1 || ret == 2) // success
	    {
		we_have_patches = ret != 0;
		mark_label(3, `check);
	    }
	    else
	    {
		// popup to inform user about the failure
		Popup::Message(_("Check for latest updates failed. View
the logs for details.
"));
		test_result = `failure;
		mark_label(3, `dash);
	    }

	    test_stage = `close;
	    return;
	}

	if (test_stage == `close)		// close connection
	{
	    if(Mode::test ()) {
		mark_label(4, `arrow);
		test_stage = `finish;
		mark_label(4, `check);
		return;
	    }

	    if(!already_up) {
		mark_label(4, `arrow);

		/* Stop connection */
		y2milestone("Connection: stop");
		// label of combobox where the log is selected
		logs = add (logs, $[ `menuname : _("Closing of Connection"),
				     `filename : "ifdown.log",
				     `prio : 14 ]);
		if(Internet::Stop(logdir + "/ifdown.log"))
		{
		    mark_label (4, `check);
		}
		else
		{
		    test_result = `failure;
		    mark_label (4, `dash);

		}
	    }

	    test_stage = `finish;
	    return;
	}
    }


    // Create logdir
    if (!(boolean)SCR::Execute (.target.mkdir, logdir))
	y2error ("can't create logdir");

    any ret = nil;

    make_dialog();

    Wizard::DisableBackButton();
    Wizard::DisableAbortButton();
    Wizard::DisableNextButton();
    UI::ChangeWidget(`id(`abort_test), `Enabled, true);
    UI::ChangeWidget(`id(`view_log), `Enabled, false);


    // loop during internet test

    SCR::Execute (.target.bash, "/bin/logger BEGIN OF YAST2 INTERNET TEST");

    while (true)
    {
	handle_stage ();

	if (test_stage == `finish)
	    break;

	ret = UI::TimeoutUserInput (250);
	UI::NormalCursor ();

	if (ret == `timeout)
	    continue;

	if (ret == `abort_test)
	{
	    if (!already_up)
		Internet::Stop ("");
	    test_result = `failure;
	    break;
	}

	y2error ("Unexpected return code: %1", ret);
    }

    UI::BusyCursor ();

    SCR::Execute (.target.bash, "/bin/logger END OF YAST2 INTERNET TEST");


    show_result ();

    copy_logs2 ();


    Wizard::EnableBackButton();
    Wizard::DisableAbortButton();
    Wizard::EnableNextButton();
    UI::ChangeWidget(`id(`abort_test), `Enabled, false);
    UI::ChangeWidget(`id(`view_log), `Enabled, true);


    // loop after internet test
    while (true)
    {
	ret = UI::UserInput();

	if (ret == `view_log)
	{
	    ShowLogs (logs, logdir);
	    continue;
	}

	if (ret == `abort || ret == `cancel)
	{
	    if (Popup::ConfirmAbort (`incomplete))
		break;
	    continue;
	}

	if (ret == `back || ret == `next)
	{
	    break;
	}

	y2error ("Unexpected return code: %1", ret);
    }


    if (ret == `next)
    {
	if (we_have_patches)
	    AskYOUDialog ();
	else
	    Internet::do_you = false;
    }

    return (symbol) ret;

/* EOF */
}
