// <summary>ソースコード：ＨＹＭＣＯ要素間接続情報クラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;

using CommonMP.HYSSOP.Interface.HSData;
using CommonMP.HYSSOP.CoreImpl.HSData;

using CommonMP.HYMCO.Interface;
using CommonMP.HYMCO.Interface.Controller;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Data;

namespace CommonMP.HYMCO.CoreImpl.Controller
{
    /// <summary><para>class outline:</para>
    /// <para>要素間接続情報</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/10/01][新規作成]</para>
    /// </remarks>
    public class McConnection : McElmConnection
    {
        //// <summary>上流エレメント </summary>
        //protected McElement m_lUpperElement=null;
        //// <summary>下流エレメント </summary>
        //protected McElement m_lLowerElement=null;

        /// <summary>接続元 </summary>
        protected McSendPort m_csFromPort;
        /// <summary>接続先 </summary>
        protected McReceivePort m_csToPort;

        /// <summary>送信情報型</summary>
        protected McTranInfo m_csInfoType;

        /// <summary>インスタンス識別ＩＤ</summary>
        protected HySID m_csID;

        /// <summary><para>method outline:</para>
        /// <para>接続生成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McConnection csCnct = CreateConnection( csUpperPortID,csUpperElement,csLowerPortID,csLowerElement ) </para>
        /// </example>
        /// <param name="csUpperPortID">上流端子識別子</param>
        /// <param name="csUpperElement">上流側要素</param>
        /// <param name="csLowerPortID">下流端子識別子</param>
        /// <param name="csLowerElement">下流側要素</param>
        /// <returns>接続</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal static McConnection CreateConnection(HySIdentifier csUpperPortID, McCmnElement csUpperElement, HySIdentifier csLowerPortID, McCmnElement csLowerElement)
        {
            McConnection csNewConnection = null;
            // 上流端子生成
            McSendPort csSndPort = csUpperElement.GetPort(csUpperPortID) as McSendPort;
            if (csSndPort == null)
            {
                csSndPort = csUpperElement.CreateSendPort();
                //McSendPort csSndPort = csUpperElement.CreateSendPort();
                csSndPort.SetID(csUpperPortID);

                // 端子設定
                csUpperElement.AddSendPort(csSndPort);
            }

            // 下流端子生成
            McReceivePort csRcvPort = csLowerElement.GetPort(csLowerPortID) as McReceivePort;
            if (csRcvPort == null)
            {
                csRcvPort = csLowerElement.CreateReceivePort();
                //McReceivePort csRcvPort = csLowerElement.CreateReceivePort();
                csRcvPort.SetID(csLowerPortID);

                // 端子設定
                csLowerElement.AddReceivePort(csRcvPort);
            }

            // 要素間接続開始
            csNewConnection = new McConnection(csSndPort, csRcvPort); // コネクション生成
            csSndPort.SetPartnerPort(csRcvPort);
            csRcvPort.SetPartnerPort(csSndPort);
            csSndPort.SetConnection(csNewConnection);
            csRcvPort.SetConnection(csNewConnection);

            return csNewConnection;
        }
        /// <summary><para>method outline:</para>
        /// <para>接続生成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McConnection csCnct = CreateExternalINConnection( csUpperPortID,csUpperElement,csLowerPortID,csLowerElement ) </para>
        /// </example>
        /// <param name="csUpperPortID">上流端子識別子</param>
        /// <param name="csUpperElement">上流側要素</param>
        /// <param name="csLowerPortID">下流端子識別子</param>
        /// <param name="csLowerElement">下流側要素</param>
        /// <returns>接続</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal static McConnection CreateExternalINConnection(HySIdentifier csUpperPortID, McCmnElement csUpperElement, HySIdentifier csLowerPortID, McCmnElement csLowerElement)
        {
            if ((csUpperElement is McGrElement) == false)
            {
                return null;
            }
            McConnection csNewConnection = null;
            // 上流端子端子生成
            McReceiveTrnsPort csRevRlyPort = csUpperElement.CreateReceivePort() as McReceiveTrnsPort;
            McSendPort csInnerSndPort = csRevRlyPort.GetInnerSndPort();
            csRevRlyPort.SetID(csUpperPortID);
            // 端子設定
            //csUpperElement.AddSendPort(csRevRlyPort); <- これはダメ：　中継端子であるため、Ｇｒ要素内からは、ReceivePortと見なされる
            csUpperElement.AddReceivePort(csRevRlyPort);            
            
            // 下流端子生成
            McReceivePort csRcvPort = csLowerElement.GetPort(csLowerPortID) as McReceivePort;
            if (csRcvPort == null)
            {
                csRcvPort = csLowerElement.CreateReceivePort();
                //McReceivePort csRcvPort = csLowerElement.CreateReceivePort();
                csRcvPort.SetID(csLowerPortID);

                // 端子設定
                csLowerElement.AddReceivePort(csRcvPort);
            }

            // 要素間接続開始
            csNewConnection = new McConnection(csRevRlyPort, csRcvPort); // コネクション生成
            csRevRlyPort.SetInternalPartnerPort(csRcvPort);
            //csRcvPort.SetPartnerPort(csRevRlyPort);
            csRcvPort.SetPartnerPort(csInnerSndPort);
            csRevRlyPort.SetConnection(csNewConnection);
            csRcvPort.SetConnection(csNewConnection);

            return csNewConnection;
        }
        /// <summary><para>method outline:</para>
        /// <para>接続生成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McConnection csCnct = CreateExternalOUTConnection( csUpperPortID,csUpperElement,csLowerPortID,csLowerElement ) </para>
        /// </example>
        /// <param name="csUpperPortID">上流端子識別子</param>
        /// <param name="csUpperElement">上流側要素</param>
        /// <param name="csLowerPortID">下流端子識別子</param>
        /// <param name="csLowerElement">下流側要素</param>
        /// <returns>接続</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal static McConnection CreateExternalOUTConnection(HySIdentifier csUpperPortID, McCmnElement csUpperElement, HySIdentifier csLowerPortID, McCmnElement csLowerElement)
        {
            if ((csLowerElement is McGrElement) == false)
            {
                return null;
            }
            McConnection csNewConnection = null;

            // 上流端子生成
            McSendPort csSndPort = csUpperElement.GetPort(csUpperPortID) as McSendPort;
            if (csSndPort == null)
            {
                csSndPort = csUpperElement.CreateSendPort();
                //McSendPort csSndPort = csUpperElement.CreateSendPort();
                csSndPort.SetID(csUpperPortID);

                // 端子設定
                csUpperElement.AddSendPort(csSndPort);
            }

            // 下流端子生成
            McSendTrnsPort csSndRlyPort = csLowerElement.CreateSendPort() as McSendTrnsPort;
            McReceivePort csInnerRcvPort = csSndRlyPort.GetInnerRcvPort();
            csSndRlyPort.SetID(csLowerPortID);
            // 端子設定
            //csLowerElement.AddReceivePort(csSndRlyPort); <- これはダメ：　中継端子である為、Gr要素内からは、SendPortと見なされる
            csLowerElement.AddSendPort(csSndRlyPort);

            // 要素間接続開始
            csNewConnection = new McConnection(csSndPort, csSndRlyPort); // コネクション生成
            //csSndPort.SetPartnerPort(csSndRlyPort);
            csSndPort.SetPartnerPort(csInnerRcvPort);
            csSndRlyPort.SetInternalPartnerPort(csSndPort);
            csSndPort.SetConnection(csNewConnection);
            csSndRlyPort.SetConnection(csNewConnection);

            return csNewConnection;
        }


        //======================================
        // コンストラクター
        //======================================

        /// <summary><para>method outline:</para>
        /// <para>コンストラクター</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McConnection csCnct = new McConnection( csFromPort,csToPort ) </para>
        /// </example>
        /// <param name="csFromPort">接続元端子</param>
        /// <param name="csToPort">接続先端子</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McConnection(McSendPort csFromPort, McReceivePort csToPort)
        {
            m_csFromPort = csFromPort;
            m_csToPort = csToPort;
        }
        /// <summary><para>method outline:</para>
        /// <para>コンストラクター</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McConnection csCnct = new McConnection( csID, csFromPort,csToPort ) </para>
        /// </example>
        /// <param name="csID">識別子</param>
        /// <param name="csFromPort">接続元端子</param>
        /// <param name="csToPort">接続先端子</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McConnection(HySID csID, McSendPort csFromPort, McReceivePort csToPort)
        {
            m_csID = csID;
            m_csFromPort = csFromPort;
            m_csToPort = csToPort;
        }
        /// <summary><para>method outline:</para>
        /// <para>コンストラクター</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McConnection csCnct = new McConnection( csFromPort,csToPort ) </para>
        /// </example>
        /// <param name="csFromPort">接続元端子</param>
        /// <param name="csToPort">接続先端子(グループ化要素外部送信端子)</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McConnection(McSendPort csFromPort, McSendTrnsPort csToPort)
        {
            m_csFromPort = csFromPort;
            m_csToPort = csToPort.GetInnerRcvPort();
        }
        /// <summary><para>method outline:</para>
        /// <para>コンストラクター</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McConnection csCnct = new McConnection( csID, csFromPort,csToPort ) </para>
        /// </example>
        /// <param name="csID">識別子</param>
        /// <param name="csFromPort">接続元端子</param>
        /// <param name="csToPort">接続先端子(グループ化要素外部送信端子)</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McConnection(HySID csID, McSendPort csFromPort, McSendTrnsPort csToPort)
        {
            m_csID = csID;
            m_csFromPort = csFromPort;
            m_csToPort = csToPort.GetInnerRcvPort();
        }
        /// <summary><para>method outline:</para>
        /// <para>コンストラクター</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McConnection csCnct = new McConnection( csFromPort,csToPort ) </para>
        /// </example>
        /// <param name="csFromPort">接続元端子(グループ化要素外部受信端子)</param>
        /// <param name="csToPort">接続先端子</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McConnection(McReceiveTrnsPort csFromPort, McReceivePort csToPort)
        {
            m_csFromPort = csFromPort.GetInnerSndPort();
            m_csToPort = csToPort;
        }
        /// <summary><para>method outline:</para>
        /// <para>コンストラクター</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McConnection csCnct = new McConnection( csID, csFromPort,csToPort ) </para>
        /// </example>
        /// <param name="csID">識別子</param>
        /// <param name="csFromPort">接続元端子(グループ化要素外部受信端子)</param>
        /// <param name="csToPort">接続先端子</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McConnection(HySID csID, McReceiveTrnsPort csFromPort, McReceivePort csToPort)
        {
            m_csID = csID;
            m_csFromPort = csFromPort.GetInnerSndPort();
            m_csToPort = csToPort;
        }

        //======================================
        // 伝送データ関連メソッド
        //======================================
        /// <summary><para>method outline:</para>
        /// <para>要素間伝送情報の種別を設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetTranInfoKind(csInfo) </para>
        /// </example>
        /// <param name="csInfo">要素間伝送情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>接続のチェック用に伝送情報を設定する</para>
        /// </remarks>
        public virtual void SetTranInfoKind(McTranInfo csInfo)
        {
            m_csInfoType = csInfo;
        }
        /// <summary><para>method outline:</para>
        /// <para>送信側に要素間伝送情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetTranInfo(csInfo) </para>
        /// </example>
        /// <param name="csInfo">要素間伝送情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void SetTranInfo(McTranInfo csInfo)
        {
            //m_csInfo = csInfo;
            m_csFromPort.SetTranInfo(csInfo);
        }
        /// <summary><para>method outline:</para>
        /// <para>要素間伝送情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> McTranInfo csInf = GetTranInfo( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>要素間伝送情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual McTranInfo GetTranInfo()
        {
            //return m_csInfo;
            return m_csFromPort.GetTranInfo();
        }

        /// <summary><para>method outline:</para>
        /// <para>接続内を流れるデータの整合性チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = DataCheck( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>  true :正常　 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool DataCheck()
        {
            bool bRtn = false;
            if (m_csInfoType != null)
            {   // データの型があれば　送信データと一致しているか
                bRtn = m_csInfoType.SameKind(this.GetTranInfo());
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>プロパティ等情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SetProperty( csCnnctionID, csCnnctInfo, ref csErrorInfo)</para>
        /// </example>
        /// <param name="csCnnctionID">変更対象接続識別子</param>
        /// <param name="csCnnctInfo">変更情報</param>
        /// <param name="csErrorInfo">接続エラー情報</param>
        /// <returns>=true:変更対象であった、!=true:変更対象ではない</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>モデル生成時にモデル内部情報を設定する</para>
        /// </remarks>
        internal virtual bool SetProperty(HySID csCnnctionID, McModelInfo csCnnctInfo, ref McStructErrorInfo csErrorInfo)
        {
            bool bRtn = false;
            if (this.m_csID.Equals(csCnnctionID) == true)
            {
                bRtn = true;
                McTranInfo csTranInfo = m_csFromPort.GetTranInfo();
                McPropertyInfoRoot csRroptyInfo = csCnnctInfo.GetPropertyInfo();
                if (csTranInfo != null && csRroptyInfo != null)
                {
                    csTranInfo.SetProperty(csRroptyInfo);
                }

            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>プロパティ等情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SetProperty( csCnnctionID, csCnnctInfo, ref csErrorInfo)</para>
        /// </example>
        /// <param name="csCnnctionID">変更対象接続識別子</param>
        /// <param name="csCnnctInfo">変更情報</param>
        /// <param name="csErrorInfo">接続エラー情報</param>
        /// <returns>=true:変更対象であった、!=true:変更対象ではない</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>演算中断中にプロパティ、初期値等を変更して動作させ場合等に使用する</para>
        /// </remarks>
        internal virtual bool SetOnlineProperty(HySID csCnnctionID, McModelInfo csCnnctInfo, ref McStructErrorInfo csErrorInfo)
        {
            bool bRtn = false;
            if (this.m_csID.Equals(csCnnctionID) == true)
            {
                bRtn = true;
                McTranInfo csTranInfo = m_csFromPort.GetTranInfo();
                McPropertyInfoRoot csRroptyInfo = csCnnctInfo.GetPropertyInfo();
                if (csTranInfo != null && csRroptyInfo != null)
                {
                    csTranInfo.SetOnlineProperty(csRroptyInfo);
                }

            }
            return bRtn;
        }

        //======================================
        // Getter
        //======================================
        /// <summary><para>method outline:</para>
        /// <para>送信端子インスタンス取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> McSendPort csPort = GetSendPort( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>送信端子インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal virtual McSendPort GetSendPort()
        { return m_csFromPort; }
        /// <summary><para>method outline:</para>
        /// <para>受信端子インスタンス取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> McReceivePort csPort = GetReceivePort( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>受信端子インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal virtual McReceivePort GetReceivePort()
        {   return m_csToPort; }

        //======================================
        // ID関連メソッド
        //======================================
        /// <summary><para>method outline:</para>
        /// <para>識別子設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetID( csID ) </para>
        /// </example>
        /// <param name="csID">識別子</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void SetID(HySIdentifier csID)
        {
            m_csID = (HySID)csID;
        }
        /// <summary><para>method outline:</para>
        /// <para>識別子取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> HySIdentifier csIdentifier = GetID( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>識別子</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual HySIdentifier GetID()
        {
            return m_csID;
        }
        /// <summary><para>method outline:</para>
        /// <para>識別子による同一比較</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = Equal( sID ) </para>
        /// </example>
        /// <param name="sID">比較する種別識別子</param>
        /// <returns>  true :＝ , false:≠</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool Equal(HySIdentifier sID)
        {
            return m_csID.Equals(sID);
        }

    }
}
