using System;
using System.Text;

using System.ComponentModel;
using System.Web.UI;
using System.Drawing;
using System.Drawing.Design;
using System.Globalization;


namespace Westwind.Web.Controls
{
    /// <summary>
    /// This control allows creating client side pop up window that blocks out the 
    /// background and brings a dialog to the foreground. This control can be  used
    ///  to replace ugly alert or prompt boxes to pop up rich dialogs that must  be
    ///  edited modally. Any dialog can be popped up like this.
    /// 
    /// The background can be just an opaque color with a transparency value - the 
    /// default is black at 70% for example which gives a grey looking overlay - or
    ///  can be a custom Html element that is expanded and then made transparent as
    ///  in the following figure.
    /// 
    /// &lt;&lt;img src="images/wwModalDialog.png"&gt;&gt;
    /// 
    /// The control is based on wwDragPanel so the dialogs can be draggable and 
    /// closable. Events are available to fire when a button or the close button is
    ///  clicked with event firing either on the client or server.
    /// 
    /// The client side counter part class can be used without this server side  
    /// control and allows a few extra features, such as a mechanism to display a  
    /// dialog without controls on the page to map to.
    /// </summary>
    [DefaultProperty("ContentId"),ToolboxBitmap(typeof(System.Web.UI.WebControls.WebParts.PageCatalogPart)),
     ToolboxData("<{0}:wwModalDialog runat=\"server\"\r\nstyle=\"background:white;display:none;\" width=\"400px\"\r\nOkButtonId=\"MessageBoxOk\" ContentId=\"MessageBoxContent\">\r\n<div id=\"MessageBoxHeader\" class='gridheader'>Header</div>\r\n<div style=\"padding:10px;\">\r\n<div id=\"MessageBoxContent\"></div>\r\n<hr />\r\n<input type=\"button\" id=\"MessageBoxOk\" value=\"Close Dialog\"/>\r\n</div>\r\n</{0}:wwModalDialog>")]
    public class wwModalDialog : wwDragPanel
    {

        /// <summary>
        /// The opacity of of the overlay background in a decimal percentage. Default to .85
        /// </summary>    
        [Description("The opacity of of the overlay background in a decimal percentage.)"),
         DefaultValue(typeof(decimal),".75"), Category("Modal")]
        public decimal BackgroundOpacity
        {
            get { return _BackgroundOpacity; }
            set { _BackgroundOpacity = value; }
        }
        private decimal _BackgroundOpacity = .75M;

        /// <summary>
        /// The client ID of the element that receives the content message. 
        /// If not specified the message is written to the body of the control.
        /// </summary>
        [Description("Optional Id of the content area that is set when showDialog is called. If not provided the main dialog is updated)"),
         DefaultValue(""), Category("Modal")]
        public string ContentId
        {
            get { return _ContentId; }
            set { _ContentId = value; }
        }
        private string _ContentId = "";

        /// <summary>
        /// ID of a header element that receives the Title when calling showDialog()
        /// on the client. Optional - if not specified the header is not set which 
        /// means the dialog displays as designed.
        /// </summary>
        [Description("Optional Id of the header area that is set when showDialog is called. If not no title is set"),
         Category("Modal"),DefaultValue("")]
        public string HeaderId
        {
          get { return _HeaderId; }
          set { _HeaderId = value; }
        }
        private string _HeaderId = "";

        /// <summary>
        /// Optional Id that is to be used for the shaded Overlay. This allows you
        /// to create a colored or otherwise designed background that pops over the
        /// existing content.
        /// </summary>
        [Description("Optional client ID for a DOM element to be used for the overlay. If not specified a default element will be created.)"),
         DefaultValue(""), Category("Modal")]        
        public string OverlayId
        {
            get { return _OverlayId; }
            set { _OverlayId = value; }
        }
        private string _OverlayId = "";

        /// <summary>
        /// When true fades in the background by slowly increasing reducing
        /// opacity of the background
        /// </summary>
        [Description("When true fades the background in slowly increasing the opacity."),
         DefaultValue(false),Category("Modal")]
        public bool FadeinBackground
        {
            get { return _FadeinBackground; }
            set { _FadeinBackground = value; }
        }
        private bool _FadeinBackground = false;
        
        /// <summary>
        /// The ID of the button that is used to close the dialog. A button and this
        /// ID are required.
        /// </summary>
        [Description("Required client ID for the OK button that closes the dialog.)"),
         DefaultValue(""), Category("Modal")]        
        public string OkButtonId
        {
            get { return _OkButtonId; }
            set { _OkButtonId = value; }
        }
        private string _OkButtonId = "";

        /// <summary>
        /// Optional ID of a button that is used to cancel an operation. This 
        /// Id is optional and should be used only if you have a second button.
        /// </summary>
        [Description("Optional client ID for the CancelButton. Not required.)"),
         DefaultValue(""), Category("Modal")]
        public string CancelButtonId
        {
            get { return _CancelButtonId; }
            set { _CancelButtonId = value; }
        }
        private string _CancelButtonId = "";

        /// <summary>
        /// Client side event handler that is fired when a button is clicked
        /// to close the dialog. The handler receives two parameters: 1 or 0
        /// for Ok or Cancel respectively, and the object that fired the event
        /// which is the button. This allows you to retrieve the caption.
        /// </summary>
        [Description("Optional Client Even Handler for that traps button clicks. Handler receives 1 for Ok, 0 for Cancel)"),
        DefaultValue(""), Category("Modal")]
        public string OnClientDialogClick
        {
            get { return _OnClientDialogClick; }
            set { _OnClientDialogClick = value; }
        }
        private string _OnClientDialogClick = "";

        /// <summary>
        /// The zIndex value for the overlay and dialog. This value must be 
        /// higher than any other control on the page in order for the 
        /// dialog to pop up on top. 
        /// </summary>
        [Description("The zIndex for the overlay and dialog.)"),
        DefaultValue(10000), Category("Modal")]
        public int zIndex
        {
            get { return _zIndex; }
            set { _zIndex = value; }
        }
        private int _zIndex = 10000;

        /// <summary>
        /// Determines the location of thte JavaScript support file if ScriptLocationType is set to ExternalFile
        /// </summary>
        [Description("Determines where the script file is loaded from. Values include: WebResource, EmbeddedInPage or the link to the wwScriptLibrary.js file (ie. ~/images/wwscriptlibrary.js)"),
        DefaultValue("WebResource"), Category("Callback"),
       Editor("System.Web.UI.Design.UrlEditor", typeof(UITypeEditor))]
        public string ScriptLocation
        {
            get { return _ScriptLocation; }
            set { _ScriptLocation = value; }
        }
        private string _ScriptLocation = "WebResource";

      

        /// <summary>
        /// Override to force simple IDs all around
        /// </summary>
        public override string UniqueID
        {
            get
            {
                return this.ID;
            }
        }

        /// <summary>
        /// Override to force simple IDs all around
        /// </summary>
        public override string ClientID
        {
            get
            {
                return this.ID;
            }
        }        
   
#region Non-browsables

        //[Browsable(false)]
        //public bool Closable
        //{
        //    get { return _closable; }
        //    set { _closable = value; }
        //}
        //private bool _closable = false;


        [Browsable(false)]
        public new string OnClientCloseHandler
        {
            get { return base.OnClientCloseHandler; }
            set { base.OnClientCloseHandler = value; }
        }
#endregion

        
        protected override void OnLoad(EventArgs e)
        {
            if (this.Visible)
            {
                StringBuilder Script = new StringBuilder();
                Script.Append(
    "var " + this.ID + " = new wwModalDialog('" + this.ID + "','" + this.OkButtonId + "','" + this.CancelButtonId + "','" + this.ContentId + "','" + this.HeaderId + "');\r\n");

                if ((this.FadeinBackground))
                    Script.Append(this.ID + ".fadeinBackground = true;\r\n");

                if (!string.IsNullOrEmpty(this.OverlayId))
                    Script.Append(this.ID + ".overlayId = '" + this.OverlayId + "';\r\n");

                if (!string.IsNullOrEmpty(this.OnClientDialogClick))
                    Script.Append(this.ID + ".dialogHandler = " + this.OnClientDialogClick + ";\r\n");

                Script.Append(this.ID + ".backgroundOpacity = " + this.BackgroundOpacity.ToString(CultureInfo.InvariantCulture.NumberFormat) + ";\r\n" +
                               this.ID + ".zIndex = " + this.zIndex.ToString() + ";\r\n");

                ClientScriptProxy.Current.RegisterStartupScript(this, typeof(ControlResources), this.ID + "_ModalStart", Script.ToString(), true);
            }
            base.OnLoad(e);
        }

        protected override void OnPreRender(EventArgs e)
        {
            if (!this.Visible)
                return;


            // *** real pre-render code

            // *** Hook up the close behavior for the close button
            if (this.Closable)
            {
                if (string.IsNullOrEmpty(this.OnClientCloseHandler))
                    this.OnClientCloseHandler = this.ID + ".hideDialog";
            }

            // *** Need to set the modal dialog's shadow in addition
            // *** to the drag panel's to ensure the original display
            // *** is respecting the offset.
            if (this.ShadowOffset != 0)
                this.ShowScript += this.ID + ".boxObj.showShadow(" + 
                            this.ShadowOpacity.ToString(CultureInfo.InvariantCulture.NumberFormat) + "," +
                            this.ShadowOffset.ToString() + ");\r\n";

            if (!string.IsNullOrEmpty(this.ShowScript))
                ClientScriptProxy.Current.RegisterStartupScript(this, typeof(ControlResources), this.ID + "_ShowScript", this.ShowScript, true);


            base.OnPreRender(e);            
        }


        private string ShowScript = null;

        /// <summary>
        /// A server side display method that forces the modal dialog to be to be displayed
        /// when the page loads. 
        /// 
        /// Note the page still loads and when you click out of the dialog you will
        /// be back on the original page. IOW, it's still full client side behavior
        /// even though activated through the server.
        /// </summary>
        /// <param name="Message"></param>
        /// <param name="Title"></param>
        public void Show(string Message, string Title)
        {
            this.Show(Message, Title, "", "");
        }

        /// <summary>
        /// Shows the dialog as designed without any customizations
        /// </summary>
        public void Show()
        {
            this.Show("", "", "", "");
        }

        /// <summary>
        /// A server side display method that forces the modal dialog to be to be displayed
        /// when the page loads. 
        /// 
        /// Note the page still loads and when you click out of the dialog you will
        /// be back on the original page. IOW, it's still full client side behavior
        /// even though activated through the server.
        /// </summary>
        /// <param name="Message"></param>
        /// <param name="Title"></param>
        /// <param name="OkButtonText"></param>
        /// <param name="CancelButtonText"></param>
        public void Show(string Message, string Title, string OkButtonText, string CancelButtonText)
        {
            Message = Message ?? "";
            Title = Title ?? "";
            OkButtonText = OkButtonText ?? "";
            CancelButtonText = CancelButtonText ?? "";

            // *** Hooks up window.load event handler - we'll need to load the page first
            // *** or IE will choke on the script execution.
            this.ShowScript = string.Format(
@"wwEvent.addEventListener(window,'load',function() {{ {0}.showDialog('{1}','{2}','{3}','{4}') }},false);
", this.ID, Message, Title, OkButtonText, CancelButtonText);

        }

    }
}
