/**
 * File:
 *   OSRPopup.ycp
 *
 * Module:
 *   Popups for the YaST2 system repair tool.
 *
 * Author:
 *   Johannes Buchhold <jbuch@suse.de>
 *
 * $Id: OSRPopup.ycp 22046 2005-03-01 10:15:00Z jsuchome $
 */

{
  module "OSRPopup";

  import "Label";
  import "Popup";

  import "OSRMode";
  import "OSRCommon";

  textdomain "repair";

  // pushbutton label
  global string skip_label	=  _("&Skip");
  // pushbutton label
  global string repair_label	=  _("&Repair");
  // pushbutton label
  global string recover_label   =  _("&Recover");
  // pushbutton label
  global string ignore_label	=  _("&Ignore");
  global string help_label	=  Label::HelpButton();

  // dialog caption: "YaST system repair Help"
  global string help_headline  = OSRCommon::tool_name + _(" Help");

  /**
   * Sublayout for other layouts.
   */
  define term repair_layout_internal(term center_box, term button_box )``{
      return `HBox(
		   `HSpacing(1),
		   `HCenter(
			    `HSquash(
				     `VBox(
					   `HCenter(
						    `HSquash(
							     center_box
							     )
						    ),
					   `VSpacing(1  ),
					   `HSquash(button_box)
					   )
				     )
			    ),
		   `HSpacing(1)
		   );
  }

  /**
   * Layout for some following dialog.
   */
  define term repair_layout(string headline,  string help_text, term special_contents ) ``{

      term help_button   = `Empty();

      // enable the help-button if a help-text is specified
      if ( help_text != "" && help_text != "TODO" )
      {
	  help_button   = `PushButton(`id(`osr_popup_help), Label::HelpButton() );
      }
      else
      {
	  help_button   = `PushButton(`id(`osr_popup_help), `opt(`disabled), Label::HelpButton());
      }

      term button_box    = `HBox(
				 `PushButton(`id(`osr_popup_repair), `opt(`default), repair_label ),
				 `PushButton(`id(`osr_popup_skip), skip_label),
				 `HSpacing(2),
				 `Right( help_button )
				 );

      // put the window-contents alltogether
      return repair_layout_internal ( `VBox(
					    `Left(`Heading(headline)),
					    special_contents
					    ),
				      button_box
				      );
  }

  /**
   * Layout for some following dialogs.
   */
  define term radio_button_popup_layout(string headline, term rb_group , boolean strict ) ``{

      term button_box    = `Empty();
      if ( strict )
      {
	  button_box    = `HBox(`HWeight(1, `PushButton(`id(`osr_popup_ok), `opt(`default), Label::OKButton())));
      }
      else
      {
	  button_box    = `HBox(
				`HWeight(1, `PushButton(`id(`osr_popup_ok), `opt(`default), Label::OKButton())),
				`HSpacing(2),
				`HWeight(1, `PushButton(`id(`osr_popup_cancel), Label::CancelButton()))
				);
      }

      // window contents alltogether
      return repair_layout_internal( `VBox(
					   `Left(`Heading(headline)),
					   `VSpacing(1),
					   `HSquash(rb_group),
					   `VSpacing(1)
					   ),
				     button_box
				     );

  }


  /**
   * Open a dialog with the term r_options in the center.
   */
  global define boolean OpenMainRepairDialog(string headline, string error_text, term r_options ) ``{

      // Build the options for the user dialog
      term contents = `HVSquash (
				`HBox(
				      `HSpacing(2),
				      `VBox(
					    `VSpacing(1),
					    `Left(`Heading( headline)),
					    `VSpacing(1),
					    `Left(`Label(error_text)),
					    `VSpacing(1),
					    `RadioButtonGroup(`id(`rb), r_options),
					    `VSpacing(1),
					    `Bottom( `HSquash(`HBox(
							  `PushButton(`id(`ok), `opt(`default ), Label::OKButton()),
							  `PushButton(`id(`cancel), skip_label),
							  `HSpacing(2),
							  `Right(`PushButton(`id(`help), help_label ))
							  )))
						    ),
					    `HSpacing(2)));

      boolean ret = UI::OpenDialog( contents );
      UI::SetFocus(`id(`ok));
      return ret;
  }

  /**
   * Open the base dialog to suggest modify.
   */
  global define boolean OpenSuggestDialog(string headline, string message, string help_text, term body, integer hweight )``{

      term message_box = `VBox(`Left(`Label(message )),
			       `VSpacing(1)
			       );

      integer headline_box_wight = 20;

      if ( message == "" )
      {
	 message_box = `Empty();
	 headline_box_wight = 10;
      }

      term contents =
	  `HBox(
		`HWeight( 25, `RichText( help_text )),
		`HWeight( 1,  `HSpacing(1)),
		`HWeight( 60, `VBox(
				    `VWeight(headline_box_wight,`VBox(
						      `Left(`Heading(headline )),
						      //`VSpacing(1),
						      message_box
						      )
					     ),	
				    `VWeight(hweight, body ),
				    `VWeight(10,`VBox(
						      //`VSpacing(1),
						      `Bottom(`HBox(
								    `PushButton(`id(`ok),     repair_label ),
								    `HSpacing(2),
								    `PushButton(`id(`cancel), Label::CancelButton())
								    ))))
				    )),
		`HWeight( 1, `HSpacing(1))
		);
      boolean ret = UI::OpenDialog(contents );
      UI::SetFocus(`id(`ok));
      return ret;
  }

  /**
   * Dialog to change one field in the fstab.
   */
  global define string ChangeFieldDialog(string org_value, string description )``{

    UI::OpenDialog(
	`VBox(
	    `TextEntry(`id(`text) , description,org_value),
	    `VSpacing(1),
	    `HBox (
		`PushButton(`id(`ok), Label::OKButton()),
		`HSpacing(2),
		`PushButton(`id(`cancel), Label::CancelButton())
	    )
    ));

    string ret = "";
    if (UI::UserInput() == `ok)
	ret = (string) UI::QueryWidget(`id(`text),`Value );
    else ret = nil;

    UI::CloseDialog();
    return ret;
}

  /**
   *  This method opens a new popup window that displays the error message.
   *  It provides a repair button, a skip button and a help button.
   *
   *  @param string The headline of the popup window.
   *  @param string The message text to display in the window.
   *  @param string The help text to display when the user presses the help button.
   *                If the help text is empty, no help button will be displayed.
   *  @return boolean True if the repair button was pressed by the user.
   *  @example boolean repair_question = OSRPopup::Repair( "Error detected", error_message, help_text);
   */
  global define boolean Repair(string headline, string message, string help_text ) ``{

    // In automatic-mode no window is displayed and true (== Repair)
    // is returned,
    // in detection-mode no window is displayed and false (== Skip)
    // is returned -> only detection, no repair
    if (OSRMode::automatic || OSRMode::detection)
    {
	return true;
    }

    term special_contents = `VBox (
				`VSpacing(0.2),
				`Left(`Label(message))
    );
    UI::OpenDialog(`opt(`decorated),
	repair_layout( headline,  help_text, special_contents ));
    UI::SetFocus(`id(`osr_popup_repair));

    any ret = `next;

    // stay into the while-loop until the user presses Skip or Repair
    while ((ret != `osr_popup_skip) && (ret != `osr_popup_repair))
    {
	ret = UI::UserInput();
	if (ret == `osr_popup_help)
	{
	    // launch text-popup to display help-text
	    Popup::LongText(help_headline , `RichText(help_text), 50, 20);
	}
    }

    UI::CloseDialog();

    return (ret == `osr_popup_repair);
  };

  /**
   *  This method opens a popup window that offers the specified items to the
   *  user. The items can be selected in a RadioButtonGroup. A default item has to
   *  be specified. It is marked as selected from start. If the default is "", the
   *  first item in the list is marked as selected.
   *  It provides an OK button and a Cancel button. If OK is pressed the selected
   *  item is returned as a string, if cancel is pressed, the specified default is
   *  returned.
   *
   *  @param string headline The headline of the popup window.
   *  @param string message The message text to display in the window.
   *  @param list item_list The list of items. This has to be a list of strings.
   *  @param string default The default value to mark as selected.
   *  @param boolean strict If strict is true, only an OK-pushbutton is displayed,
   *         if strict is false both OK- and Cancel-button are displayed.
   *  @return string The selected item, the default if cancel is pressed.
   *  @example string result = OSRPopup::RadioButtonGroup("Test", "This is just a test.", ["a", "b", "c"], "b", true);
   */
  global define string RadioButtonGroup(string headline, string message,
					list<string> item_list, string default,
					boolean strict) ``{

      string result = default;
      if (OSRMode::automatic || OSRMode::detection )
      {
	  return "";
      }

      if (size(item_list) == 0)
      {
	  y2error("RadioButtonGroup: empty list as parameter: %1", item_list);
	  return "";
      }

      term rb_group     = `Empty();
      term rbs          = `VBox( `Left(`Label(message)), `VSpacing(1));
      integer i		= 0;

      // create the radio buttons dynamically referring to the item_list
      while (i >= 0 && i < size(item_list))
      {
	string item = item_list[i]:"";

	// if the current radio button is the default enable it
	term rb  = `Left (
	    `RadioButton (`id(i), item,
		((item == default) || ((default == "") && (i == 0)))
	));
	rbs = add(rbs, rb);
	i   = i + 1;
      }
      // RadioButtonGroup
      rb_group      = `RadioButtonGroup(`id(`rb_group), rbs );

      UI::OpenDialog (`opt(`decorated),
	radio_button_popup_layout (headline, rb_group , strict ));

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

      // handling of the user-input, return the activatet list-item
      if (  UI::UserInput()  == `osr_popup_ok)
      {
	  integer current = (integer)
	    UI::QueryWidget(`id(`rb_group), `CurrentButton);
	  result	  = item_list[current]:default;
      }
      else {
	  result = "";
      }

      UI::CloseDialog();

      return result;
  };

  /**
   *  This method opens a popup window that offers the specified items to the
   *  user. The items can be selected in a RadioButtonGroup. A default item has to
   *  be specified. It is marked as selected from start. If the default is "", the
   *  first item in the list is marked as selected.
   *  It provides an OK button and a Cancel button. If OK is pressed the selected
   *  item is returned as a string, if cancel is pressed, the specified cancel-value
   *  is returned. 
   *
   *  @param string headline The headline of the popup window.
   *  @param string message The message text to display in the window.
   *  @param list item_list The list of items. This has to be a list of strings.
   *  @param string default The default value to mark as selected.
   *  @param string cancel The value that will be returned when pressing cancel.
   *  @param boolean strict If strict is true, only an OK-pushbutton is displayed,
   *         if strict is false both OK- and Cancel-button are displayed.
   *  @return string The selected item, the default if cancel is pressed.
   *  @example string result = OSRPopup::RadioButtonGroupText("Test",
   *                                                  "This is a test.",
   *						      [["a" , "First choice"], ["b", "Second choice"]],
   *						      "b",
   *						      "cancel",
   *						      true); 
   */
  global define string RadioButtonGroupText(string headline, string message,
					    list<list> item_list,
					    string default,
					    string cancel, boolean strict) ``{

      string result = default;

      if (OSRMode::automatic || OSRMode::detection )
      {
	  return "";
      }

      if (size(item_list) == 0)
      {
	  y2error("RadioButtonGroup: empty list as parameter: %1", item_list);
	  return "";
      }
      
      term rb_group      = `Empty();
      term rbs           = `VBox(`Left(`Label(message)));
      
      integer i 	 = 0;
      // create the radio buttons dynamically referring to the item_list

      while (i >= 0 && i < size(item_list))
      {
	  // an item looks like ["a", "First choice"]
	  list   item      = item_list [i]:[];
	  string item_key  = item[0]:"";
	  string item_text = item[1]:"";

	  // create a radio button for the current item
	  // if the current radio button is the default enable it
	  term rb  = `Left(
		      `RadioButton(
				   `id(i),
				   (item_text == "") ? item_key : item_key + " - " + item_text,
				   ((item_key == default) || ((default == "") && (i == 0)))  // enable the specified default
				   )
		      );

	  // add the current radio button to the radio buttons
	  rbs = add(rbs, rb);
	  
	  // go to the next item in the list
	  i   = i + 1;
      }

      // RadioButtonGroup
      rb_group      = `RadioButtonGroup(
					`id(`rb_group),
					rbs
					);

      UI::OpenDialog ( `opt(`decorated),
	radio_button_popup_layout (headline, rb_group, strict )
      );

      // set the focus to the OK button
      UI::SetFocus(`id(`osr_popup_ok));

      // handling of the user-input, return the activatet list-item
      any ret = UI::UserInput();
      if (ret == `osr_popup_ok)
      {
	  integer current = (integer)
	    UI::QueryWidget(`id(`rb_group), `CurrentButton);

	  // get the chosen item and return its key
	  result = item_list [current, 0]:"";
      }
      else if (ret == `osr_popup_cancel)
      {
	  result = cancel;
      }

      UI::CloseDialog();
      return result;
  };

  global define map CheckBoxDialog (string headline, string message,
				    list<list> boxes )``{

    term check_group = `VBox (`Left (`Label (message)), `VSpacing (1));

    foreach(list box, boxes, ``{
	check_group = add (check_group,
	    `Left(`CheckBox(`id( box[0]:""), box[1]:"", box[2]:false ))
	);
    });

    UI::OpenDialog (`opt(`decorated),
	radio_button_popup_layout (headline, check_group , true ));

    // set the focus to the OK button
    UI::SetFocus(`id(`osr_popup_ok));

    // handling of the user-input, return the activatet list-item
    map selected	= $[];
    any ret		= UI::UserInput();

    if (ret == `osr_popup_ok)
    {
	foreach (list box, boxes, ``{
	    selected [box[0]:""] = UI::QueryWidget(`id(box[0]:"" ), `Value );
	});
    }

    UI::CloseDialog();
    return selected;
  }


  define term build_multi_box(string box_headline, list<list> item_list )``{

      list<term> items = [];
      foreach (list item, item_list ,``{
	  items = add(items, `item(`id(item[0]:""), item[0]:"", item[1]:true ));
      });
      return `MultiSelectionBox( `id(`selection_box ), box_headline, items );
  }

  /**
   * A dialog with to messages and a multi selection box in the center.
   */
  global define list<string> MultiSelectionBox(string     headline,
					       string     message_top,
					       string     message_bottom,
					       string     help_text,
					       string     box_headline,
					       list<list> item_list,
					       list<list> special_buttons_list )``{

      term special_buttons = `HBox();
      map  special_symbol_to_action = $[];
      foreach ( list special_button, special_buttons_list, ``{
	  special_buttons = add( special_buttons, special_button[0]:`Empty());
	  special_symbol_to_action[special_button[1]:`empty] =
	    special_button[2]:OSRCommon::EmptyList;
      });
      term multi_box_with_text =  `VBox(`Left(`Label(message_top )),
					`VSpacing(1),
					`ReplacePoint(`id(`rp), build_multi_box(box_headline, item_list)),
					special_buttons,
					`VSpacing(1),
					`Left(`Label(message_bottom )),
					`VSpacing(1));
      UI::OpenDialog(
		     `opt(`decorated),
		     repair_layout(headline, help_text, multi_box_with_text )
		     );

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

      list<string> ret_list	= [];
      any ret			= `next;

      repeat
      {
	  ret = UI::UserInput();

	  if (ret == `osr_popup_help)
	  {
	      // launch text-popup to display help-text
	      Popup::LongText( help_headline , `RichText(help_text), 50, 20);
	  }
	  else if ( ret == `osr_popup_repair )
	  {
	      ret_list = (list<string>)
		UI::QueryWidget(`id(`selection_box), `SelectedItems );
	  }
	  else
	  {
	      // eval special button action define.
	      if ( haskey( special_symbol_to_action, ret ))
	      {
		  list () f =special_symbol_to_action[ret]:OSRCommon::EmptyList;
		  UI::ReplaceWidget(`id(`rp),
		    build_multi_box(box_headline, (list<list>) f()));
	      }
	  }
      }
      until( ret == `osr_popup_repair || ret  == `osr_popup_skip );

      UI::CloseDialog();

      return ret_list;
  }

// --- moved from OSRRepairUI:

/**
 * Build (return) a description text for a label in the help_text field.
 * @param label the label
 * @param description the description text for the label.
 * @return the formatted label help text
 */
global define string build_label_description (string label, string description) ``{
    return sformat ("<P><B>%1</B><BR>%2</P>",
        mergestring (splitstring (label, "&"), ""), description);
}

}//EOF
