// 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 TERASOLUNA.Fw.Common.Logging;

namespace TERASOLUNA.Fw.Web.Configuration.Page
{
    /// <summary>
    /// ページ設定ファイルから PageConfiguration 設定情報を取得します。
    /// </summary>
    /// <remarks>特になし。</remarks>
    public abstract class PageConfiguration
    {
        /// <summary>
        /// <see cref="ILog"/> 実装クラスのインスタンスです。
        /// </summary>
        /// <remarks>
        /// ログ出力に利用します。
        /// </remarks>
        private static ILog _log = LogFactory.GetLogger(typeof(PageConfiguration));

        /// <summary>
        /// 二重押下防止機能が「無効」に指定されているページかチェックします。
        /// </summary>
        /// <param name="pagePath">送信元 page 情報の識別子。</param>
        /// <returns>
        /// 二重押下防止機能が「無効」に指定されている場合は true 。それ以外の場合は false 。
        /// 既定値は false です。
        /// </returns>
        /// <remarks>
        /// ページ設定ファイルから、<paramref name="pagePath"/> に対応する preventDoubleSubmit 属性の値を取得し、
        /// "off" の場合は true を返します。それ以外は false を返します。既定値は false です。
        /// </remarks>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="pagePath"/> が null 参照です。
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="pagePath"/> が空文字です。
        /// </exception>
        /// <exception cref="System.Configuration.ConfigurationErrorsException">
        /// 構成ファイルを読み込むことができません。
        /// </exception>
        public static bool CheckUnAvailablePage(string pagePath)
        {
            if (pagePath == null)
            {
                ArgumentNullException exception = new ArgumentNullException("pagePath");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "pagePath"), exception);
                }
                throw exception;
            }
            if (pagePath.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "pagePath");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }

            bool ret = false;
            foreach (PageElement pageItem in TerasolunaWebConfiguration.PageConfigSection.Pages)
            {
                if (String.Equals(pagePath, pageItem.Path, StringComparison.CurrentCultureIgnoreCase))
                {
                    //　同名の　PATH　が存在
                    if ("off".Equals(pageItem.Pds))
                    {
                        //preventDoubleSubmit設定が"OFF"(無効指定)である場合
                        ret = true;
                    }
                    break;
                }
            }

            if (_log.IsTraceEnabled)
            {
                if (ret)
                {
                    _log.Trace(string.Format(Properties.Resources.T_PREVENT_DOUBLE_SUBMIT_OFF, pagePath));
                }
                else
                {
                    _log.Trace(string.Format(Properties.Resources.T_PREVENT_DOUBLE_SUBMIT_ON, pagePath));
                }
            }

            return ret;
        }

        /// <summary>
        /// 指定されたページに対応するページ ID を取得します。
        /// </summary>
        /// <param name="pagePath">取得するページ ID の識別子。</param>
        /// <returns>
        /// <paramref name="pagePath"/> に指定されたページに対応するページ ID 。
        /// 対応するページ ID が存在しない場合は null 参照。
        /// </returns>
        /// <remarks>
        /// ページ設定ファイルから、<paramref name="pagePath"/> の値に対応する name 属性の値を取得します。
        /// 対応する name 属性の値が存在しない場合、null 参照を返します。
        /// </remarks>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="pagePath"/> が null 参照です。
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="pagePath"/> が空文字です。
        /// </exception>
        /// <exception cref="System.Configuration.ConfigurationErrorsException">
        /// 構成ファイルを読み込むことができませんでした。
        /// </exception>
        public static string GetPageID(string pagePath)
        {
            if (pagePath == null)
            {
                ArgumentNullException exception = new ArgumentNullException("pagePath");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "pagePath"), exception);
                }
                throw exception;
            }
            if (pagePath.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "pagePath");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }

            string pageID = null;
            foreach (PageElement pageItem in TerasolunaWebConfiguration.PageConfigSection.Pages)
            {
                if (String.Equals(pagePath, pageItem.Path, StringComparison.CurrentCultureIgnoreCase))
                {   //同じPathの pageElement が存在する場合
                    PageElement pageElement = TerasolunaWebConfiguration.PageConfigSection.Pages[pageItem.Name];
                    pageID = pageElement.Name;
                    break;
                }
            }

            if (_log.IsTraceEnabled)
            {
                if (pageID == null)
                {
                    _log.Trace(string.Format(Properties.Resources.T_PAGE_CONFIGURATION_NOT_LOAD_PAGE_ID, pagePath));
                }
                else
                {
                    _log.Trace(string.Format(Properties.Resources.T_PAGE_CONFIGURATION_LOAD_PAGE_ID, pagePath, pageID));
                }
            }

            // PagesCollectionに該当するpagePathのエレメントがない場合、nullを返却
            return pageID;
        }

        /// <summary>
        /// 指定されたページ ID に対応するページを取得します。
        /// </summary>
        /// <param name="pageID">取得するページの識別子。</param>
        /// <returns>
        /// <paramref name="pageID"/> に指定されたページ ID に対応するページ。
        /// 対応するページが存在しない場合は null 参照。
        /// </returns>
        /// <remarks>
        /// ページ設定ファイルから、<paramref name="pageID"/> の値に対応する path 属性の値を取得します。
        /// 対応する path 属性の値が存在しない場合、null 参照を返します。
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="pageID"/> が null 参照です。
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="pageID"/> が空文字です。
        /// </exception>
        /// <exception cref="System.Configuration.ConfigurationErrorsException">
        /// 構成ファイルを読み込むことができませんでした。
        /// </exception>
        public static string GetPath(string pageID)
        {
            if (pageID == null)
            {
                ArgumentNullException exception = new ArgumentNullException("pageID");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "pageID"), exception);
                }
                throw exception;
            }
            if (pageID.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "pageID");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }
            PageElement pageElement = TerasolunaWebConfiguration.PageConfigSection.Pages[pageID];

            string pagePath = null;
            if (pageElement != null)
            {
                pagePath = pageElement.Path;
            }

            if (_log.IsTraceEnabled)
            {
                if (pagePath == null)
                {
                    _log.Trace(string.Format(Properties.Resources.T_PAGE_CONFIGURATION_NOT_LOAD_PATH, pageID));
                }
                else
                {
                    _log.Trace(string.Format(Properties.Resources.T_PAGE_CONFIGURATION_LOAD_PATH, pageID, pagePath));
                }
            }

            return pagePath;
        }

        /// <summary>
        /// トークンの確認が有効かどうかを示す値を取得します。
        /// </summary>
        /// <param name="pagePath">現在のページのパス。</param>
        /// <returns>
        /// トークンの確認が有効な場合 true 。有効で無い場合 false 。
        /// 既定値は true です。
        /// </returns>
        /// <remarks>
        /// ページ設定ファイルから、<paramref name="pagePath"/> に対応する checkToken 属性の値を取得し、
        /// "off" の場合は false を返します。それ以外は true を返します。既定値は true です。
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="pagePath"/> が null 参照です。
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="pagePath"/> が空文字です。
        /// </exception>
        /// <exception cref="System.Configuration.ConfigurationErrorsException">
        /// 構成ファイルを読み込むことができませんでした。
        /// </exception>
        public static bool IsCheckTokenEnabled(string pagePath)
        {
            if (pagePath == null)
            {
                ArgumentNullException exception = new ArgumentNullException("pagePath");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "pagePath"), exception);
                }
                throw exception;
            }
            if (pagePath.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "pagePath");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }

            // デフォルトの戻り値は有効
            bool ret = true;

            foreach (PageElement pageItem in TerasolunaWebConfiguration.PageConfigSection.Pages)
            {
                if (String.Equals(pagePath, pageItem.Path, StringComparison.CurrentCultureIgnoreCase))
                {
                    //同名のPATHが存在
                    if (String.Equals(pageItem.CheckToken, "off", StringComparison.CurrentCultureIgnoreCase))
                    {
                        //CheckToken設定が"OFF"(無効指定)である場合
                        ret = false;
                    }
                    break;
                }
            }

            if (_log.IsTraceEnabled)
            {
                if (ret)
                {
                    _log.Trace(string.Format(Properties.Resources.T_CHECK_TOKEN_ON, pagePath));
                }
                else
                {
                    _log.Trace(string.Format(Properties.Resources.T_CHECK_TOKEN_OFF, pagePath));
                }
            }

            return ret;
        }

        /// <summary>
        /// トークンの発行が有効かどうかを示す値を取得します。
        /// </summary>
        /// <param name="pagePath">現在のページのパス。</param>
        /// <returns>
        /// トークンの発行が有効な場合 true 。有効で無い場合 false 。
        /// 既定値は true です。
        /// </returns>
        /// <remarks>
        /// ページ設定ファイルから、<paramref name="pagePath"/> に対応する setToken 属性の値を取得し、
        /// "off" の場合は false を返します。それ以外は true を返します。既定値は true です。
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="pagePath"/> が null 参照です。
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="pagePath"/> が空文字です。
        /// </exception>
        /// <exception cref="System.Configuration.ConfigurationErrorsException">
        /// 構成ファイルを読み込むことができませんでした。
        /// </exception>
        public static bool IsSetTokenEnabled(string pagePath)
        {
            if (pagePath == null)
            {
                ArgumentNullException exception = new ArgumentNullException("pagePath");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "pagePath"), exception);
                }
                throw exception;
            }
            if (pagePath.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "pagePath");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }

            // デフォルトの戻り値は有効
            bool ret = true;

            foreach (PageElement pageItem in TerasolunaWebConfiguration.PageConfigSection.Pages)
            {
                if (String.Equals(pagePath, pageItem.Path, StringComparison.CurrentCultureIgnoreCase))
                {
                    // 同名の PATH が存在
                    if (String.Equals(pageItem.SetToken, "off", StringComparison.CurrentCultureIgnoreCase))
                    {
                        // CheckToken 設定が"OFF"(無効指定)である場合
                        ret = false;
                    }
                    break;
                }
            }

            if (_log.IsTraceEnabled)
            {
                if (ret)
                {
                    _log.Trace(string.Format(Properties.Resources.T_SET_TOKEN_ON, pagePath));
                }
                else
                {
                    _log.Trace(string.Format(Properties.Resources.T_SET_TOKEN_OFF, pagePath));
                }
            }

            return ret;
        }
        /// <summary>
        /// トークンの更新が有効かどうかを示す値を取得します。
        /// </summary>
        /// <param name="pagePath">現在のページのパス。</param>
        /// <returns>
        /// トークンの更新が有効な場合 true 。有効で無い場合 false 。
        /// 既定値は true です。
        /// </returns>
        /// <remarks>
        /// ページ設定ファイルから、<paramref name="pagePath"/> に対応する updateToken 属性の値を取得し、
        /// "off" の場合は false を返します。それ以外は true を返します。既定値は true です。<br/>
        ///  updateToken 属性は、ファイルダウンロード処理や AutoPostBack が有効なコントロールを含むページに
        /// 対して設定してください。
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="pagePath"/> が null 参照です。
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="pagePath"/> が空文字です。
        /// </exception>
        /// <exception cref="System.Configuration.ConfigurationErrorsException">
        /// 構成ファイルを読み込むことができませんでした。
        /// </exception>
        public static bool IsUpdateTokenEnabled(string pagePath)
        {
            if (pagePath == null)
            {
                ArgumentNullException exception = new ArgumentNullException("pagePath");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "pagePath"), exception);
                }
                throw exception;
            }
            if (pagePath.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "pagePath");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }

            // デフォルトの戻り値は有効
            bool ret = true;

            foreach (PageElement pageItem in TerasolunaWebConfiguration.PageConfigSection.Pages)
            {
                if (String.Equals(pagePath, pageItem.Path, StringComparison.CurrentCultureIgnoreCase))
                {
                    // 同名の PATH が存在
                    if (String.Equals(pageItem.UpdateToken, "off", StringComparison.CurrentCultureIgnoreCase))
                    {
                        // UpdateToken 設定が"OFF"(更新しない)である場合
                        ret = false;
                    }
                    break;
                }
            }

            if (_log.IsTraceEnabled)
            {
                if (ret)
                {
                    _log.Trace(string.Format(Properties.Resources.T_UPDATE_TOKEN_ON, pagePath));
                }
                else
                {
                    _log.Trace(string.Format(Properties.Resources.T_UPDATE_TOKEN_OFF, pagePath));
                }
            }

            return ret;
        }
    }
}
