/***********************************************************************
 *  File: usernameDialog-gtk.cs
 *  Author: Juan Carlos Luciani (jluciani@novell.com)
 * 
 *  Namespace: Novell.Security.ClientPasswordManager
 * 
 *  Classes implemented: UsernameDialog.
 * 
 *  Copyright (C) 2004 Novell, Inc.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 ***********************************************************************/

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Text.RegularExpressions;
using Gtk;

namespace Novell.Security.ClientPasswordManager
{
   /// <summary>
   /// Class implements user name dialog leveraging Gtk#.
   /// </summary>
   sealed public class usernameDialog : Dialog
   {
      #region Class Members and Defines

      private Entry m_userNameEntry;
      private Button m_okButton;
      private Button m_cancelButton;

      // The following strings need to be localized
      private static string m_userNameLabelText = "User name:";

      #endregion

      /// <summary>
      /// Class implements dialog to notify user that it needs to
      /// input the user name.
      /// </summary>
      private class inputRequiredDialog: Dialog
      {
         #region Class Members and Defines

         // The following strings need to be localized
         private static string m_inputRequiredLabelText = "User name required";

         #endregion

         /// <summary>
         /// Constructor.
         /// </summary>
         /// <param name="title">Title to be used with the dialog.</param>
         public inputRequiredDialog(string title) : base()
         {
            this.Title = title;
            this.HasSeparator = false;
            this.Resizable = false;
            this.Modal = true;
            this.DefaultResponse = ResponseType.Ok;

            HBox h = new HBox();
            h.BorderWidth = 12;
            h.Spacing = 6;

            Gtk.Image i = new Gtk.Image();
            i.SetFromStock(Stock.DialogError, IconSize.Dialog);
            i.SetAlignment(0.5F, 0);
            h.PackStart(i, false, false, 0);

            Label l = new Label("<span weight=\"bold\" size=\"larger\">"
               + m_inputRequiredLabelText
               + "</span>");
            l.LineWrap = true;
            l.UseMarkup = true;
            l.Selectable = false;
            l.Xalign = 0;
            l.Yalign = 0;
            h.PackStart(l, false, false, 0);

            h.ShowAll();
            this.VBox.Add(h);

            this.AddButton(Stock.Ok, ResponseType.Ok);
         }
      }

      /// <summary>
      /// Constructor.
      /// </summary>
      /// <param name="title">Title to use for the dialog.</param>
      public usernameDialog(string title) : base()
      {
         this.Title = title;
         this.HasSeparator = false;
         this.Resizable = false;
         this.Modal = true;

         HBox h = new HBox();
         h.BorderWidth = 12;
         h.Spacing = 6;

         Label l = new Label(m_userNameLabelText);
         l.Xalign = 0;
         h.PackStart(l, false, false, 0);

         m_userNameEntry = new Entry();
         m_userNameEntry.ActivatesDefault = true;
         h.PackStart(m_userNameEntry, true, true, 0);

         h.ShowAll();
         this.VBox.Add(h);

         m_okButton = new Button(Stock.Ok);
         m_okButton.CanDefault = true;
         this.AddActionWidget(m_okButton, ResponseType.Ok);

         m_cancelButton = new Button(Stock.Cancel);
         this.AddActionWidget(m_cancelButton, ResponseType.Cancel);

         this.DefaultResponse = ResponseType.Ok;
         this.ShowAll();
      }

      /// <summary>
      /// Shows the dialog and gathers the user input.
      /// </summary>
      /// <param name="parent">Window owner.</param>
      /// <returns>True if the user input was gathered, else false.</returns>
      public bool Invoke(Window parent)
      {
         bool retVal;

         while (true)
         {
            // Set focus on the entry widget, display the dialog, and
            // hide it once it is answered.
            this.Focus = m_userNameEntry;
            this.TransientFor = parent;
            ResponseType resp = (ResponseType) this.Run();
            this.Hide();

            // Proceed based on the dialog response value
            if (resp == ResponseType.Ok)
            {
               // Verify that the user entered the desired information
               if (m_userNameEntry.Text.Length != 0)
               {
                  // The user name was entered, indicate success and
                  // get ready to exit.
                  retVal = true;
                  break;
               }
               else
               {
                  // Inform the user that it must enter a name
                  inputRequiredDialog errorDialog = new inputRequiredDialog(Title);
                  errorDialog.Run();
                  errorDialog.Hide();

                  // Show the user name dialog again
                  continue;
               }
            }
            else
            {
               // The user either hit the cancel button or closed
               // the window.
               retVal = false;
               break;
            }
         }

         return retVal;
      }

      /// <summary>
      /// Gets the name entered by the user.
      /// </summary>
      /// <returns>NetworkCredential object or null if not successful</returns>
      public System.String userName { get {return m_userNameEntry.Text;}}
   }

   /// <summary>
   /// Class wrapper around the usernameDialog class. This wrapper is utilized
   /// to hide the use of Gtk# from its users.
   /// </summary>
   public class UsernameDialog
   {
      #region Class Members and Defines
      
      usernameDialog m_dialog;

      // The following strings need to be localized
      private static string m_titleStartText = "Login to ";
      private static string m_titleRealmText = ", Realm: ";

      #endregion
      
      /// <summary>
      /// Constructor.
      /// </summary>
      /// <param name="svcName">Name of service on whose behalf we are acquiring user name.</param>
      public UsernameDialog(string svcName)
      {
         // Instantiate the dialog with the appropriate title
         m_dialog = new usernameDialog(m_titleStartText + svcName);
      }

      /// <summary>
      /// Constructor.
      /// </summary>
      /// <param name="svcName">Name of service on whose behalf we are acquiring user name.</param>
      /// <param name="realm">Name of realm to which the service belongs, can be empty string or null.</param>
      public UsernameDialog(string svcName, string realm)
      {
         // Instantiate the dialog with the appropriate title
         if (realm != null && realm.Length != 0)
         {
            m_dialog = new usernameDialog(m_titleStartText + svcName + m_titleRealmText + realm);
         }
         else
         {
            m_dialog = new usernameDialog(m_titleStartText + svcName);
         }
      }

      /// <summary>
      /// Shows the dialog and gathers the user input.
      /// </summary>
      /// <param name="o">Window owner.</param>
      /// <returns>True if the user input was gathered, else false.</returns>
      public bool Invoke(System.Object o)
      {
         return m_dialog.Invoke((Window) o);
      }

      /// <summary>
      /// Gets the name entered by the user.
      /// </summary>
      public System.String userName { get {return m_dialog.userName;}}
   }
}