/**
 * File:
 *	inst_timezone.ycp
 *
 * Authors:
 *	Klaus   Kämpf <kkaempf@suse.de>
 *	Michael Hager <mike@suse.de>
 *	Stefan  Hundhammer <sh@suse.de>
 *
 * Summary:
 *	Let the user choose the timezone.
 *
 * $Id: inst_timezone.ycp 22162 2005-03-02 14:11:40Z jsuchome $
 */
{
textdomain "country";

import "Arch";
import "Label";
import "Mode";
import "Misc";
import "Popup";
import "Stage";
import "Timezone";
import "Wizard";
import "GetInstArgs";

symbol hwclock_s_initial = `none;

define void SetTimezone (symbol hwclock, string timezone, boolean really,
                         boolean changed_time)
{

    y2milestone( "SetTimezone hw %1, tz %2 really %3 tchanged %4 initial:%5",
                 hwclock, timezone, really, changed_time, hwclock_s_initial );

    // simulate the time change
    if (!really && hwclock != hwclock_s_initial)
	Timezone::diff = (hwclock==`hwclock_utc)?1:-1;
    else
	Timezone::diff = 0;

    y2milestone( "SetTimezone diff %1", Timezone::diff );

    Timezone::hwclock = (hwclock == `hwclock_utc) ? "-u" : "--localtime";
    Timezone::Set (timezone, really);

    // Redisplay date/time.
    //
    UI::ChangeWidget(`id(`date), `Value, Timezone::GetDateTime (really, true));
};

define boolean SetTimeDialog() {
    // help text
    string htext = _("<p>This dialog offers the possibility to change
the system time and date.</p>
");
    // help text
    htext = htext + _("Current system time and date are displayed in
the input fields. Change them to the correct values and press the
Apply button.
");

    map val = Timezone::GetDateTimeMap();

    UI::OpenDialog( `opt(`decorated),
	`HBox(
	    `HWeight(30, `RichText( htext )),
	    `HStretch(),
	    `HSpacing(1),
	    `HWeight(70,
		`VBox(
		    `HBox( `HSpacing(60) ),
		    // heading text
		    `Heading( _("Change System Date and Time") ),
		    `VSpacing(3),
		    `VStretch(),
		    `HBox ( `HSpacing(10),
			   // label text, do not change "HH:MM:SS"
		           `Label( _("Current Time in HH:MM:SS Format")),
			   `HStretch()
		    ),
		    `HBox (`HSpacing(10),
		           `TextEntry( `id(`hour), `opt(`shrinkable), "",
			               val["hour"]:"" ),
			   `Label( ":" ),
		           `TextEntry( `id(`minute), `opt(`shrinkable), "",
			                val["minute"]:"" ),
			   `Label( ":" ),
		           `TextEntry( `id(`second), `opt(`shrinkable), "",
			                val["second"]:"" ),
			   `HSpacing(32)
		    ),
		    `VSpacing(2),
		    `VStretch(),
		    `HBox( `HSpacing(10),
			   // label text, do not change "DD-MM-YYYY"
			   `Label( _("Current Date in DD-MM-YYYY Format") ),
			   `HStretch() ),
		    `HBox( `HSpacing(10),
			   `VBox( `HSpacing(2),
			          `TextEntry( `id(`day), `opt(`shrinkable), "",
				              val["day"]:"" )),
			   `Label( "-" ),
			   `VBox( `HSpacing(2),
				  `TextEntry( `id(`month), `opt(`shrinkable),
				               "", val["month"]:"" )),
			   `Label( "-" ),
			   `VBox( `HSpacing(4),
				  `TextEntry( `id(`year), `opt(`shrinkable), "",
				              val["year"]:"" )),
			   `HSpacing(30)
		    ),
		    `VSpacing(4),
		    `VStretch(),
		    `HBox(
		        // button text
			`PushButton(`id(`apply), `opt(`default), _("&Apply")),
			`PushButton(`id(`cancel), Label::CancelButton() ))
		    )
		)
    ));
    UI::ChangeWidget( `id(`hour), `ValidChars, "0123456789" );
    UI::ChangeWidget( `id(`minute), `ValidChars, "0123456789" );
    UI::ChangeWidget( `id(`second), `ValidChars, "0123456789" );
    UI::ChangeWidget( `id(`day), `ValidChars, "0123456789" );
    UI::ChangeWidget( `id(`month), `ValidChars, "0123456789" );
    UI::ChangeWidget( `id(`year), `ValidChars, "0123456789" );
    any ret = `cancel;
    repeat
    {
	ret = UI::UserInput();
	y2milestone( "UserInput ret:%1", ret );
	if (ret == `apply)
	{
	    string hour = (string) UI::QueryWidget( `id(`hour), `Value );
	    string minute = (string) UI::QueryWidget( `id(`minute), `Value );
	    string second = (string) UI::QueryWidget( `id(`second), `Value );
	    string day = (string) UI::QueryWidget( `id(`day), `Value );
	    string month = (string) UI::QueryWidget( `id(`month), `Value );
	    string year = (string) UI::QueryWidget( `id(`year), `Value );
	    if (!Timezone::CheckTime (hour, minute, second))
	    {
		string tmp = sformat( "%1:%2:%3", hour, minute, second );
		// popup text
		tmp = sformat( _("Invalid time (HH:MM:SS) %1
Enter the correct time.
"), tmp );
		Popup::Error( tmp );
		ret = `retry;
	    }
	    else if( !Timezone::CheckDate( day, month, year ))
	    {
		string tmp = sformat( "%1-%2-%3", day, month, year );
		// popup text
		tmp = sformat( _("Invalid date (DD-MM-YYYY) %1
Enter the correct date.
"), tmp );
		Popup::Error( tmp );
		ret = `retry;
	    }
	    else
	    {
		Timezone::SetTime( year, month, day, hour, minute, second );
	    }
	}
    }
    until( ret==`apply || ret==`cancel );
    UI::CloseDialog();
    return( ret==`apply );
};

/* ----------------------------------------------------------------------
 * Timezone
 * ----------------------------------------------------------------------*/

    // get current timezone and clock setting
    //
    boolean changed_time = false;
    string timezone	= Timezone::timezone;
    string timezone_old = timezone;
    string hwclock	= Timezone::hwclock;

    y2milestone ( "timezone_old %1", timezone_old );

    timezone		= Timezone::UpdateTimezone (timezone);

    // Autoinstall
    if (Mode::config ())
    {
	import "AutoinstGeneral";
	timezone = AutoinstGeneral::Clock["timezone"]:"";
	hwclock = ( AutoinstGeneral::Clock["hwclock"]:"" == "UTC" ) ? "-u"  : "--localtime";
    }

    string date = "";

    if (Mode::config () || Mode::mode () == "firstboot")
    {
	Wizard::HideAbortButton();
    }
    else
    {
	Wizard::OpenAcceptDialog();
	// do this as early as possible for instant user feedback!
    }

    // build up timezone selection box
    //
    term timezonesel = `ReplacePoint (`id(`tzsel),
	// title for selection box 'timezone'
	`SelectionBox (`id (`timezone), `opt(`notify), _("Time &Zone")));

    term region = `SelectionBox (
	// label text
	`id(`region),`opt(`notify,`immediate), _("&Region"),Timezone::Region());

    boolean utc_only = Timezone::utc_only ();
    y2milestone( "utc_only %1", utc_only );

    /* ----------------------------------------------------------------------
     * Build dialog
     * ----------------------------------------------------------------------*/

    // Assign system date and time.
    //
    date = Timezone::GetDateTime(true, true);

    term hw_clock = `Empty();
    if (!utc_only)
    {
	hw_clock = `VBox(
	    `ComboBox (
		`id (`hwclock), `opt(`hstretch, `notify ),
		// combo box label
		 _("&Hardware clock set to"),
		[
		    // ComboBox entry: hardware clock set to local time
		    `item (`id (`hwclock_localtime), _("local time"),
			    (hwclock == "--localtime")),

		    // ComboBox entry: hardware clock set UTC
		    `item (`id(`hwclock_utc ), _("UTC"), (hwclock == "-u"))
		]
	    ),
	    `Label (`id(`date), `opt(`hstretch), date)
	);
    }
    else
    {
	hw_clock = `VBox (
	    // label text
	    `Label (`id(`hwcl), `opt(`hstretch), _("Hardware clock set to")),
	    `Label( `id(`date), `opt(`hstretch), date )
	);
    }

    term settime = `Empty();
    if (!Arch::s390 () && !Mode::config ())
    {
	// button text
	settime = `PushButton( `id(`settime), _("Change &Time or Date"));
    }

    term contents = `VBox (`HBox (
				`HWeight( 3, `HStretch() ),
				`HWeight( 40, region ),
				`HWeight( 5, `HStretch() ),
				`HWeight( 50, timezonesel ),
				`HWeight( 2, `HStretch() )
				),
			   `HBox(
				`HWeight( 3, `HStretch() ),
				`HWeight( 40, settime ),
				`HWeight( 5, `HStretch() ),
				`HWeight( 50, hw_clock ),
				`HWeight( 2, `HStretch() )
				),
			   `VSpacing()
    );

    // help for timezone screen
    string help_text = _("<p>
Select the appropriate <b>time zone</b>:
Choose the country or region where you are located.
</p>
");

    if (!utc_only)
    {
	// help for time calculation basis:
	// hardware clock references local time or UTC?
	help_text = help_text + _("<p>
Specify whether the <b>hardware clock</b> of your machine is set to local time or UTC.
</p>");
	// additional help for hardware clock
	help_text = help_text + _("<p>
Most PCs that also have other operating systems installed (such as Microsoft
Windows) use local time.
</p>");

	// additional help for hardware clock
	help_text = help_text + _("<p>
Machines that have only Linux installed should be
set to Universal Time Coordinated (UTC).
</p>
");
    }


    // general help trailer
    help_text = help_text + _("<p>
If you are unsure, use the default values already selected.
</p>");

    // Screen title for timezone screen
    Wizard::SetContents (_("Clock and Time Zone Configuration"), contents,
			 help_text, GetInstArgs::enable_back(), GetInstArgs::enable_next() );

    Wizard::SetDesktopIcon ("timezone");
    if ( Stage::initial () || Stage::firstboot ())
    {
	Wizard::SetTitleIcon( "timezone" );
    }


    // Initially set the current timezone to establish a consistent state.
    //
    integer sel = 0;
    if (Mode::config ())
    {
	import "AutoinstGeneral";
	sel = Timezone::Set (AutoinstGeneral::Clock["timezone"]:"", true);
    }
    else
    {
	sel = Timezone::Set (timezone, true);
    }

    symbol hwclock_s = (hwclock=="-u") ? `hwclock_utc : `hwclock_localtime;
    symbol hwclock_s_old = hwclock_s;
    hwclock_s_initial = hwclock_s;

    UI::ChangeWidget (`id(`region), `CurrentItem, sel);
    UI::ReplaceWidget (`id(`tzsel),
	`SelectionBox ( `id(`timezone), `opt(`notify),
	    // label text
	    _("Time &Zone"), Timezone::Selection (sel))
    );
    UI::ChangeWidget (`id(`timezone), `CurrentItem, Timezone::timezone);

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

    any ret = nil;

    Timezone::PushVal();

    repeat
    {
	ret = Wizard::UserInput();

	y2debug( "ret %1", ret );

	if (!Mode::config () && ret == `abort && Popup::ConfirmAbort(`painless))
	{
	    break;
	}
	if (ret == `region)
	{
	    integer num = (integer)UI::QueryWidget( `id(`region), `CurrentItem);
	    y2milestone ("selected region %1", num);
	    UI::ReplaceWidget (`id(`tzsel),
		`SelectionBox ( `id(`timezone), `opt(`notify),
		    // label text
		    _("Time &Zone"), Timezone::Selection (num))
	    );
	    if (num == sel)
	    {
		UI::ChangeWidget (`id(`timezone), `CurrentItem, timezone);
	    }
	}
	else if (ret == `settime)
	{
	    if (SetTimeDialog())
	    {
		UI::ChangeWidget(`id(`date), `Value,
		    Timezone::GetDateTime (false, true));
		changed_time = true;
	    }
	}
	else if (ret == `next || ret == `timezone || ret == `hwclock)
	{
	    // Get current settings.
	    // UTC vs. localtime, only if needed
	    //
	    hwclock_s = `hwclock_utc;
	    if (!utc_only)
	    {
		hwclock_s = (symbol)UI::QueryWidget( `id(`hwclock), `Value );
	    }
	    if (ret == `timezone)
	    {
		sel = (integer)UI::QueryWidget( `id(`region), `CurrentItem );
	    }

	    timezone = (string)UI::QueryWidget( `id(`timezone ), `CurrentItem );

	    if (timezone == nil || size(timezone) == 0)
	    {
	        // popup text
		Popup::Error( _("Select a valid time zone.") );
		ret = `again;
		timezone = timezone_old;
	    }
	    y2milestone ("timezone %1 ret %2", timezone, ret);

	    // Change only if s.th. has really changed.
	    //
	    if (Mode::config ())
	    {
		// Autoinstall
		import "AutoinstGeneral";
		AutoinstGeneral::Clock["hwclock"] = ( hwclock_s == `hwclock_utc ) ? "UTC" : "localtime";
		AutoinstGeneral::Clock["timezone"]  =  timezone;
	    }
	    else
	    {
		if( timezone != timezone_old || hwclock_s != hwclock_s_old ||
		    ret == `next)
		{
		    if (timezone != timezone_old)
		    {
			changed_time = true;
		    }
		    timezone_old	= timezone;
		    hwclock_s_old	= hwclock_s;
		    SetTimezone (hwclock_s, timezone, ret==`next, changed_time);
		}

		if (ret == `next)
		{
		    // User wants to keep his changes.
		    // Set user_decision flag in timezone module.
		    //
		    Timezone::user_decision	= true;
		    Timezone::user_hwclock	= true;
		}
	    }
	}
    } until ( ret == `next || ret == `back || ret == `cancel );

    if( ret != `next )
    {
	Timezone::PopVal();
    }

    if (Mode::mode () != "firstboot")
    {
        Wizard::CloseDialog();
    }

    return ret;
}
