/**
 * File:
 *	inst_language.ycp
 *
 * Module:
 *	inst_language.ycp
 *
 * Authors:
 *	Klaus   Kämpf <kkaempf@suse.de>
 *	Michael Hager <mike@suse.de>
 *	Stefan  Hundhammer <sh@suse.de>
 *	Thomas Roelz <tom@suse.de>
 *
 * Summary:
 *	Let the user choose the language.
 *
 * $Id: inst_language.ycp 22532 2005-03-14 15:39:31Z jsuchome $
 *
 */
{
    textdomain "country";

    import "Console";
    import "Encoding";
    import "GetInstArgs";
    import "Installation";
    import "Keyboard";
    import "Label";
    import "Language";
    import "Misc";
    import "Mode";
    import "PackageCallbacksInit";
    import "PackageSystem";
    import "Popup";
    import "Report";
    import "Stage";
    import "Timezone";
    import "Wizard";



define void LanguageExpertDialog()
    ``{
    symbol ret = `none;
    // help text for keyboard expert screen
    string help_text = _("<p>
Here, fine-tune settings for the language handling.
These settings are written into the file <b>/etc/sysconfig/language</b>.
</p>
");

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

    help_text = help_text + _("<p>
<b>LANG Environment Settings for User root:</b>
This determines how the locale variables (LC_*) are set for the root user.</p>
<p><b>ctype only:</b> root has the same LC_CTYPE as a normal user. Other values
are unset.<br>
<b>yes:</b> root has the same locale settings as normal user.<br>
<b>no:</b> root has all locale variables unset.
</p>
");

    UI::OpenDialog( `opt(`decorated  ),
		    `HBox(
			`HWeight(40, `RichText( help_text )),
			`HStretch(),
			`HSpacing(1),
			`HWeight(60,
			    `VBox(
				`HSpacing( 45 ),
				// heading text
				`Heading( _("Language Details") ),
				`VSpacing(`opt(`vstretch), 2),
				`Left(`ComboBox(
				    `id(`rootlang),
				    _("Locale Settings for User &root"),
				    // do not translate "ctype"
				    [ `item( `id("ctype"), _("ctype Only")),
				      `item( `id("yes"), _("Yes")),
				      `item( `id("no"), _("No")) ] )),
				`VSpacing(`opt(`vstretch), 1),
				`Left(`CheckBox( `id(`use_utf8),
						 _("Use &UTF-8 Encoding"),
						 true )),
				`VSpacing(`opt(`vstretch), 7),
				`HBox(
				     `PushButton(`id(`ok), `opt(`default),
						 Label::OKButton() ),
				     `PushButton(`id(`cancel),
				                 Label::CancelButton() )
				     )
				))
			 ));
    map val = Language::GetExpertValues();
    map val_on_entry = val;
    y2milestone( "map %1", val );
    UI::ChangeWidget( `id(`rootlang), `Value, val["rootlang"]:"ctype" );
    UI::ChangeWidget( `id(`use_utf8), `Value, val["use_utf8"]:false );
    repeat
	{
	ret = (symbol)UI::UserInput();
	if( ret == `ok )
	    {
	    val = $[];
	    val["rootlang"] = UI::QueryWidget( `id(`rootlang), `Value );
	    val["use_utf8"] = UI::QueryWidget( `id(`use_utf8), `Value );
	    y2milestone( "map ok %1", val );
	    Language::SetExpertValues( val );
	    if (val != val_on_entry)
		Language::ExpertSettingsChanged = true;
	    }
	} until ( ret == `cancel || ret == `ok );
    UI::CloseDialog();
    };

    /* ----------------------------------------------------------------------
     * Language
     * ----------------------------------------------------------------------*/

    boolean source_initialized	= false;

    // Check if the current call should be treated as the first run (3rd param).
    // In this case if the user exits with next the the current setting
    // will be made the default that is restored with "Reset to defaults".
    //
    boolean set_default = GetInstArgs::argmap()["first_run"]:"no" == "yes";

    y2milestone("set_default: %1", set_default );

    // when the possibility for selecting more languages should be shown
    // (this includes differet UI layout)
    boolean more_languages	= true;

    string language		= Language::language;

    list<string>languages	= splitstring (Language::languages, ",");
    if (! contains (languages, language))
	languages	= add (languages, language);


    Language::WfmSetLanguage ();

    // Build the contents of the dialog.

    // build up language selection box
    // with the default selection according to Language::language

    // set up selection list with default item

    boolean use_ascii	= Language::GetTextMode ();
    boolean show_expert = true;

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

    // heading text
    string heading_text = _("Language selection");

    if (Stage::initial () && set_default && !Mode::repair ())
    {
	import "Product";

	// initial heading for language selection
	// (first 'user visible' screen)
	// %1 is product name
	heading_text = sformat (_("Welcome to the %1 Installation"),
	    Product::name);
    }
    else if (Mode::repair ())
    {
	// heading text
	heading_text = _("Welcome to YaST2 System Repair");
    }

    if (Stage::initial () && set_default)
    {
	show_expert	= false;
	more_languages	= false;
    }

    // sort language by ASCII with help of a map
    // $[ "ascii-name" : [ "user-readable-string", "code" ], ...]
    // the "user-readable-string" is either ascii or utf8, depending
    // on textmode probed above (workaround because there isn't any
    // usable console font for all languages).

    map<string,list> languageselsort = mapmap (
	string lang_code, list lang_info, Language::Selection(), {
	    string key	= lang_info [1]:lang_code;
	    return $[
		key		: [
		    lang_info[use_ascii ? 1 : 0]:"",
		    lang_code,
		    lang_info[2]:key
		]
	    ];
	}
    );

    // mapping of language name (translated) to language code
    map lang2code		= $[];
    // list of language names (translated)
    list<string> lang_list	= [];
    foreach (any name, list codelist, languageselsort, {
	lang2code [codelist[2]:""]	= codelist[1]:"";
	lang_list	= add (lang_list, codelist[2]:"");
    });

    term languagesel = `SelectionBox (`id(`language), `opt(`notify), "",
	maplist (any name, list codelist, languageselsort,
		``(`item(`id(codelist[1]:""), codelist[0]:"",
			  (language == codelist[1]:""))))
    );


    term expert = `HStretch();

    if (show_expert)
    {
	expert = `VBox (
	    `Label (""),
	    // button label
	    `PushButton (`id(`expert), _("&Details"))
	);
    }

    term contents = `VBox (
	`VSpacing (0.3),
	`HBox (
	    `HWeight (25, `HStretch ()),
	    `HWeight (50,
		`VBox (
		    // label text
		    `Left (`Label (_("Select your language:"))),
		    languagesel
		)
	    ),
	    `HWeight (25, expert)
	),
	`VSpacing (2)
    );

    // if checkboxes for adapting keyboard and timezone should be shown
    boolean adapt_term = more_languages;

    if (more_languages)
    {

	term primary_language_term =
	    `ComboBox (`id(`language), `opt (`notify),
	    // combo box label
	    _("Primary &Language"),
	    maplist (any name, list codelist, languageselsort,
		``(`item (
		    `id(codelist[1]:""),
		    codelist[0]:"",
		    language == codelist[1]:"")
		)
	    )
	);

	term languages_term = `MultiSelectionBox (`id(`languages),
	    // multiselection box label
	    _("&Secondary Languages"),
	    maplist (string trans_lang, lsort (lang_list), {
		string code	= lang2code [trans_lang]:"";
		return
		    `item (`id (code), trans_lang, contains (languages, code));
	    })
	);

	term primary_term = `HBox (
			`Left (primary_language_term),
			`Right (expert)
	);

	if (adapt_term)
	{
	    string kb		=
		Keyboard::GetKeyboardForLanguage (language, "english-us");
	    string kbd_name	= Keyboard::Selection ()[kb]:"";
	    string tz		=
		Timezone::GetTimezoneForLanguage (language, "US/Mountain");
	    string tmz_name	= Timezone::GetTimezoneCountry (tz);

	    // frame label
	    primary_term = `Frame (_("Primary Language Settings"), `HBox (
		`HSpacing (0.5),
		`VBox (
		    primary_term,
		    `VSpacing (0.5),
		    `Left (`CheckBox (`id (`adapt_kbd),
			// check box label (%1 is keyboard layout name)
			sformat(_("Adapt &Keyboard Layout to '%1'"),kbd_name))),
		    `Left (`CheckBox (`id (`adapt_tmz),
			// check box label (%1 is country name)
			sformat (_("Adapt &Time Zone to '%1'"), tmz_name))),
		    `VSpacing (0.5)
		),
		`HSpacing (0.5))
	    );
	}

	contents = `VBox (
	    `VSpacing (),
	    `HBox (
		`HSpacing (2),
		`VBox (
		    primary_term,
		    `VSpacing (),
		    `ReplacePoint (`id(`rplangs), languages_term),
		    `VSpacing (0.5)
		),
		`HSpacing (2)
	    ),
	    `VSpacing()
	);
    }

    string help_text = "";

    if (Stage::initial ())
    {
	// help text for initial (first time) language screen
	help_text = _("<p>
Choose the <b>language</b> to use during installation and for
the installed system.
</p>
");

	// help text, continued
	help_text = help_text + _("<p>
Click <b>Accept</b> to proceed to the next dialog.
</p>
");

	// help text, continued
	help_text = help_text + _("<p>
<b><i>Nothing will happen</i></b> to your computer until you confirm
all your settings in the last installation dialog.
</p>
");
	if (set_default)
	{
	    // help text, continued
	    help_text = help_text + _("<p>
You can select <b>Abort Installation</b> at any time to abort the
installation process.
</p>
");
	}
    }
    else
    {
	// different help text when called after installation
	// in an installed system
	help_text = _("<p>
Choose the new <b>language</b> for your system.
</p>\n");
    }

    if (more_languages)
    {
	// help text when "multiple languages" are suported 1/2
	help_text = _("<p>
Choose the new <b>primary language</b> for your system.
</p>\n");

	// help text for 'adapt keyboard checkbox'
	help_text	= help_text + _("<p>
Check <b>Adapt Keyboard Layout</b> to adapt the keyboard layout to the primary language.
</p>
") +

	_("<p>
Check <b>Adapt Time Zone</b> to change the current time zone according to the primary language.
</p>
");

	// help text when "multiple languages" are suported 2/2
	help_text	= help_text + _("<p>
<b>Secondary Languages</b><br>
In the selection box, specify additional languages to use on your system.
</p>
");

	help_text       = help_text + _("<p>
Additional packages with support for the selected primary and secondary languages will be installed. Packages no longer needed will be removed.
</p>");
    }

    // Screen title for the first interactive dialog

    Wizard::SetContents (heading_text, contents, help_text,GetInstArgs::enable_back() , GetInstArgs::enable_next());

    Wizard::SetDesktopIcon("yast-language");

    // No .desktop files in inst-sys - use icon explicitly
    if (Stage::initial ())
	Wizard::SetTitleIcon ("babelfish");

    // Get the user input.
    //
    any ret = nil;

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

    // adapt keyboard for language?
    boolean kbd_adapt = (Stage::initial () && set_default);
    // adapt timezone for language?
    boolean tmz_adapt = (Stage::initial () && set_default);


    repeat
    {
	ret = Wizard::UserInput();
	y2debug ("UserInput() returned %1", ret);

	if (ret == `abort && Popup::ConfirmAbort (`painless))
	{
	    Wizard::RestoreNextButton();
	    return `abort;
	}

	if (ret==`expert)
	{
	    LanguageExpertDialog();
	}

	if (ret == `help)
	{
	    Wizard::ShowHelp( help_text );
	}

	if (ret == `next || ret == `language)
	{
	    // Get the selected language.
	    //
	    language = more_languages ?
		(string) UI::QueryWidget(`id(`language), `Value) :
		(string) UI::QueryWidget(`id(`language), `CurrentItem);

	    if (adapt_term)
	    {
		kbd_adapt = (boolean) UI::QueryWidget (`id(`adapt_kbd), `Value);
		tmz_adapt = (boolean) UI::QueryWidget (`id(`adapt_tmz), `Value);
	    }

	    if (ret == `next && Language::IncompleteTranslation (language))
	    {
		// continue/cancel message
		if (!Popup::ContinueCancel (_("Translation of the primary language is not complete.
Some texts may be displayed in English.
")))
		{
		    ret = `not_next;
		    continue;
		}
	    }

	    if (language != Language::language)
	    {
		y2milestone ("Language changed from %1 to %2", Language::language, language);
		if (more_languages)
		{
		    list<string> selected_languages = (list<string>)
			UI::QueryWidget (`id(`languages),`SelectedItems);
		    if (!contains (selected_languages, language))
		    {
			selected_languages = add (selected_languages, language);
		    }
		    selected_languages	= filter (string l, selected_languages,
			``(l != Language::language));

		    UI::ReplaceWidget (`id(`rplangs),
			`MultiSelectionBox (`id(`languages),
			    // multiselection box label
			    _("Secondary Languages"),
			    maplist (string trans_lang, lsort (lang_list), {
				string code	= lang2code [trans_lang]:"";
				return `item (`id (code), trans_lang,
				    contains(selected_languages, code));
			    })
			));

		    if (ret != `next)
		    {
			Language::languages =
			    mergestring (selected_languages, ",");
		    }
		}


		if (Stage::initial () && set_default)
		{
		    Timezone::ResetZonemap ();
		}

		// Set it in the Language module.
		//
		Language::Set (language);

		// Set Console font
		//
		Console::SelectFont (language);

		// Set it in YaST2
		Language::WfmSetLanguage ();

		if (ret != `next)
		{
		    // Display newly translated dialog.
		    //
		    Wizard::SetFocusToNextButton();
		    return (`again);
		}
	    }

	    if (ret == `next)
	    {
		// Language has been set already.
		// On first run store users decision as default.
		//
		if (set_default)
		{
		    y2milestone("Resetting to default language");
		    Language::SetDefault();
		}

		if (tmz_adapt)
		{
		    Timezone::SetTimezoneForLanguage (language);
		}
		else
		{
		    Timezone::user_decision = true;
		}

		if (kbd_adapt)
		{
		    Keyboard::SetKeyboardForLanguage (language);
		    if (Stage::initial () && set_default)
		    {
			Keyboard::SetKeyboardDefault();
		    }
		}
		else
		{
		    Keyboard::user_decision = true;
		}

		if (!Stage::initial () && !Mode::update ())
		{
		    // save settings (rest is saved in LanguageWrite)
		    if (kbd_adapt)
			Keyboard::Save (true);
		    if (tmz_adapt)
			Timezone::Save ();
		}
		y2milestone ("Language: '%1', system encoding '%2'", language,
		             WFM::GetEncoding());

		if (more_languages)
		{
		    list<string> selected_languages = (list<string>)
			UI::QueryWidget (`id(`languages),`SelectedItems);

		    if (!contains (selected_languages, language))
		    {
			selected_languages = add (selected_languages, language);
		    }
		    y2milestone ("selected languages: %1", selected_languages);

		    Language::languages = mergestring (selected_languages, ",");

		    // now adapt language seletions
		    if (Stage::initial () || Mode::update ())
		    {
			Pkg::SetAdditionalLocales (selected_languages);
		    }
		    else // install new packages right now
		    {
			PackageSystem::EnsureSourceInit ();
			PackageSystem::EnsureTargetInit ();

			Pkg::SetAdditionalLocales (selected_languages);

			Pkg::PkgSolve (true);

			boolean error	= false;
			// check for disk space (#50745)
			foreach (string mountpoint, list<integer> usage,
			    Pkg::TargetGetDU (),
			{
			    if (usage[2]:0 > usage[0]:0)
			    {
				error = true;
			    }
			});
			if (error)
			{
			    // error message
			    Report::Error (_("There is not enough space to install all additional packages.
Remove some languages from the selection."));
			    ret = `not_next;
			    continue;
			}

			PackageCallbacksInit::InitPackageCallbacks ();
			Pkg::PkgCommit (0);
		    }
		}
	    }
	}
    }
    until (ret == `next || ret == `back);

    // HEAVY UGLINESS  :-((((
    // Restoring in case of `back to be done outside the module because of
    // the retranslation loop in proposal_language.ycp.

    return (symbol) ret;
}
