using System;
using System.Collections.Generic;
using System.Text;
using CommonMP.HYSSOP.CoreImpl.HSDBA;
using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYMCO.CoreImpl.Data.ProjectCtl;
using CommonMP.HYMCO.CoreImpl.DBA;
using CommonMP.HYMCO.CoreImpl.Data.Tool;

namespace CommonMP.HYMCO.CoreOptions.McDBA.FileDBA
{
    /// <summary><para>class outline:</para>
    /// <para>プロジェクト情報　期間比較オブジェクト クラス</para>
    /// </summary>
    /// <remarks><para>remarks:</para>
    /// <para>プロジェクト情報の期間についての一致・不一致を調べる</para>
    /// </remarks>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2009/10/13][新規作成]</para>
    /// </remarks>
    public class McProjectModelPeriodComparer : HySDBAFieldComparer
    {
        /// <summary>
        /// 期間種別の検索条件
        /// </summary>
        private HySQueryEntryData m_csModelPeriodTypeQuery;

        /// <summary>
        /// 期間の検索条件
        /// </summary>
        private HySQueryEntryData m_csModelPeriodQuery;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="csModelPeriodTypeQuery">「期間種別」の検索条件エントリ</param>
        /// <param name="csModelPeriodQuery">「期間」の検索条件エントリ</param>
        public McProjectModelPeriodComparer(HySQueryEntryData csModelPeriodTypeQuery, HySQueryEntryData csModelPeriodQuery)
            : base()
        {
            // 内部フィールドに検索条件を記憶する
            m_csModelPeriodTypeQuery = csModelPeriodTypeQuery;
            m_csModelPeriodQuery = csModelPeriodQuery;
        }


        /// <summary><para>method outline:</para>
        /// <para>検索条件を評価する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <code>bool bRtn = Evaluate( csStockData )</code>
        /// </example>
        /// <param name="csStockData">DB登録データ</param>
        /// <returns>true:検索条件に合致する, false:合致しない</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool Evaluate(HySStockData csStockData)
        {
            if (m_csModelPeriodTypeQuery == null && m_csModelPeriodQuery == null)
            {
                // 検索条件が両方とも無指定→一致とする
                return true;
            }
            else if (m_csModelPeriodTypeQuery != null)
            {
                // 期間種別の検索条件がある→期間種別に応じて比較実行
                McProjectInfData.ModelPeriodType eModelPeriodType = (McProjectInfData.ModelPeriodType)m_csModelPeriodTypeQuery.GetValueToCompare();
                if (eModelPeriodType == McProjectInfData.ModelPeriodType.REGULARITY)
                {
                    // 期間種別＝定常→期間種別を比較
                    return CompareModelPeriodTypeRegularity(csStockData);
                }
                else
                {
                    // 期間種別＝期間→期間を比較
                    return CompareModelPeriodRange(csStockData);
                }
            }
            else
            {
                // 期間の検索条件がある→期間を比較
                return CompareModelPeriodRange(csStockData);
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>期間種別＝定常を判定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <code>bool bRtn = CompareModelPeriodTypeRegularity( csStockData )</code>
        /// </example>
        /// <param name="csStockData">DB登録データ</param>
        /// <returns>true:検索条件に合致する, false:合致しない</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool CompareModelPeriodTypeRegularity(HySStockData csStockData)
        {
            // DB保存データの追加検索キーから期間種別を取得する
            long lKeyNumber = 0;
            HySLong csModelPeriodType = null;
            HySDataHashTable csKeyInfo = (HySDataHashTable)csStockData.GetKeyInfo(ref lKeyNumber);
            if (lKeyNumber != 0)
            {
                csModelPeriodType = (HySLong)csKeyInfo.GetObject(McProjectQueryFieldNames.MODEL_PERIOD_TYPE);
            }
            // 期間種別が「定常」のものを一致とする
            if (csModelPeriodType != null && csModelPeriodType.m_lValue == (long)McProjectInfData.ModelPeriodType.REGULARITY)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>期間の範囲重なりを判定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <code>bool bRtn = CompareModelPeriodRange( csStockData )</code>
        /// </example>
        /// <param name="csStockData">DB登録データ</param>
        /// <returns>true:検索条件に合致する, false:合致しない</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private bool CompareModelPeriodRange(HySStockData csStockData)
        {
            // 検索条件の期間
            McRange csConditionRange = (McRange)m_csModelPeriodQuery.GetValueToCompare();

            // DB保存データの追加検索キーから期間を取得する
            long lKeyNumber = 0;
            McRange csDBRecordRange = null;
            HySLong csDBPeriodType = null;

            HySDataHashTable csKeyInfo = (HySDataHashTable)csStockData.GetKeyInfo(ref lKeyNumber);
            if (lKeyNumber != 0)
            {
                csDBRecordRange = (McRange)csKeyInfo.GetObject(McProjectQueryFieldNames.MODEL_PERIOD);
                csDBPeriodType = (HySLong)csKeyInfo.GetObject(McProjectQueryFieldNames.MODEL_PERIOD_TYPE);
            }

            if ((csDBPeriodType != null) && (csDBPeriodType.m_lValue == (long)McProjectInfData.ModelPeriodType.REGULARITY))
            {
                // 期間種別が定常→不一致
                return false;
            }
            if (csConditionRange == null && csDBRecordRange == null)
            {
                // 両方とも未設定→一致
                return true;
            }
            else if (csConditionRange != null && csDBRecordRange != null)
            {
                // 両方とも設定済みなら比較
                HySTime csConditionTimeFrom = (HySTime)csConditionRange.GetFrom();
                HySTime csConditionTimeTo = (HySTime)csConditionRange.GetTo();
                HySTime csDBRecordTimeFrom = (HySTime)csDBRecordRange.GetFrom();
                HySTime csDBRecordTimeTo = (HySTime)csDBRecordRange.GetTo();

                if (csDBRecordTimeFrom.Before(csConditionTimeFrom) && csDBRecordTimeFrom.Before(csConditionTimeTo) &&
                    csDBRecordTimeTo.Before(csConditionTimeFrom) && csDBRecordTimeTo.Before(csConditionTimeTo))
                {
                    // 条件より前にある→不一致
                    return false;
                }
                if (csDBRecordTimeFrom.After(csConditionTimeFrom) && csDBRecordTimeFrom.After(csConditionTimeTo) &&
                    csDBRecordTimeTo.After(csConditionTimeFrom) && csDBRecordTimeTo.After(csConditionTimeTo))
                {
                    // 条件より後ろにある→不一致
                    return false;
                }
                // 重なりがある→一致
                return true;
            }
            else
            {
                // 検索条件とDBレコードのどちらか一方のみが設定済み→不一致
                return false;
            }
        }
    }
}
