// Copyright (c) 2008, NTT DATA Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Web;
using System.Web.UI;
using TERASOLUNA.Fw.Web.Configuration.Page;

// RegisterClientScriptResource 使用し画面にスクリプトを埋め込みます。
// スクリプトは、[assembly:xx] に設定します。
// スクリプトのプロパティ［ビルドアクション］を[埋め込まれたリソース］に設定する必要があります。
[assembly: WebResource("TERASOLUNA.Fw.Web.Scripts.PreventDoubleSubmitImpl.js", "text/javascript")]
namespace TERASOLUNA.Fw.Web.HttpModule
{
    /// <summary>
    /// 任意の Submit ボタンが押されている間、全てのボタンを無効化するスクリプトをページに出力する機能を提供します。
    /// </summary>
    /// <remarks>
    /// <para>web.config に &lt;httpModules&gt; 設定が必要です。</para>
    /// </remarks>
    public class PreventDoubleSubmitImpl : IHttpModule
    {
        /// <summary>
        /// <see cref="PreventDoubleSubmitImpl"/> オブジェクトの作成時に初期化コードを呼び出します。 
        /// </summary>
        /// <remarks>
        /// <see cref="HttpApplication"/> オブジェクトの
        /// <see cref="HttpApplication.PreRequestHandlerExecute"/> イベントのイベントハンドラを登録します。
        /// </remarks>
        /// <param name="context">
        /// ASP.NET アプリケーション内のすべてのアプリケーションオブジェクトに共通のメソッド、
        /// プロパティ、およびイベントへのアクセスを提供する <see cref="HttpApplication"/>。
        /// </param> 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
        public virtual void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute += new EventHandler(Application_PreRequestHandlerExecute);
        }

        /// <summary>
        /// <see cref="PreventDoubleSubmitImpl"/> オブジェクトで使用されるリソース (メモリを除く) を解放します。 
        /// </summary>
        public virtual void Dispose()
        {
        }

        /// <summary>
        /// <see cref="HttpApplication.PostRequestHandlerExecute"/> イベントのイベントハンドラ。
        /// </summary>
        /// <remarks>
        /// 呼びだし元ページが、二重押下防止機能を無効なページに設定されている場合は
        /// Page クラスの Load イベントのイベントハンドラを登録します。
        /// それ以外の場合は何もしません。
        /// </remarks>
        /// <param name="sender">イベントのソース。</param>
        /// <param name="e">イベントデータを格納している <see cref="EventArgs"/>。</param>
        protected virtual void Application_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            HttpApplication application = sender as HttpApplication;
            Page page = application.Context.Handler as Page;

            string currentPagePath = WebUtils.GetCurrentPagePath();

            // ハンドラがPageか判定する
            if (page != null)
            {
                // 呼びだし元ページが、二重押下防止機能を無効なページに設定されているか否かを取得する。
                if (PageConfiguration.CheckUnAvailablePage(currentPagePath))
                {   //機能が無効なページとして設定されている場合はそのまま処理から抜ける。
                    return;
                }
                page.Load += new EventHandler(Page_Load);
            }
        }

        /// <summary>
        /// Page クラスの Load イベントのイベントハンドラ。
        /// </summary>
        /// <remarks>
        /// ボタンの二重押下防止用の設定スクリプトを書き出します。
        /// </remarks>
        /// <param name="sender">イベントのソース。</param>
        /// <param name="e">イベントデータを格納している <see cref="EventArgs"/> オブジェクト。</param>
        protected virtual void Page_Load(object sender, EventArgs e)
        {
            // ページオブジェクトをセット
            Page page = sender as Page;
            ClientScriptManager csm = page.ClientScript;

            // スクリプトの読込
            csm.RegisterClientScriptResource(GetType(), "TERASOLUNA.Fw.Web.Scripts.PreventDoubleSubmitImpl.js");

            // ボタンの二重押下防止用HIDDENフィールドの登録
            csm.RegisterHiddenField("__EVENTTARGET", "");

            //onsubmitイベントの設定
            csm.RegisterOnSubmitStatement(page.GetType(), "onsubmit", "btnDisabler();");

            //clidkHandlerイベント設定
            page.Form.Attributes.Add("onclick", "clickHandler()");
        }
    }
}
