// <summary>ソースコード：接続構造端子</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

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

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

namespace CommonMP.HYMCO.CoreImpl.Data.StructInfo
{
    /// <summary><para>class outline:</para>
    /// <para>接続構造端子クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2008/11/17][新規作成]</para>
    /// </remarks>
    [Serializable]
    public class McStructPort : HySDataRoot, HySVersionManagement
    {
        /// <summary>種別</summary>
        McDefine.SymbolDrawKind m_eDrawKind;

        /// <summary>ID</summary>
        protected HySIdentifier m_csID;
        /// <summary>自身を持つ要素ID</summary>
        protected HySIdentifier m_csElmID;

        // 接続情報
        /// <summary>接続元端子ID</summary>
        protected HySIdentifier m_csFromPortID;
        /// <summary>接続先端子ID</summary>
        protected HySIdentifier m_csToPortID;

        // 表示関連情報
        /// <summary>描画位置(X)</summary>
        protected long m_lX;
        /// <summary>描画位置(Y)</summary>
        protected long m_lY;
        /// <summary>描画位置(回転)</summary>
        protected long m_lRotate = (long)McDefine.HYM_DRAW_ANGLE_M90;

        // 一貫番号生成
        /// <summary>端子カウンタ</summary>
        static protected ulong m_ulPrimNo = 0UL;

        /// <summary><para>method outline:</para>
        /// <para>デフォルトコンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>使用禁止</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>使用禁止</para>
        /// </remarks>
        private McStructPort()
        {
            McStructPort.m_ulPrimNo += 1;
            //バージョン情報設定
            SetNowVersion();
        }
        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McStructPort csPort = new McStructPort(eKind)</para>
        /// </example>
        /// <param name="eKind">シンボル描画種別</param>
        /// <returns>インスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McStructPort(McDefine.SymbolDrawKind eKind)
        {
            m_eDrawKind = eKind;
            McStructPort.m_ulPrimNo += 1;
            //string sStr = DateTime.Now.Minute.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Second.ToString()
            //             + "-" + DateTime.Now.Day.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Year.ToString();
            //m_csID = new HySID("P" + ((long)eKind).ToString() + "-", m_ulPrimNo.ToString() + "-", sStr);
            string sStr = DateTime.Now.Minute.ToString() + DateTime.Now.Hour.ToString()
                         + "-" + DateTime.Now.Day.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Year.ToString();
            //m_csID = new HySID("P" + m_ulPrimNo.ToString() + DateTime.Now.Second.ToString() + "-", ((long)eKind).ToString(), sStr);
            m_csID = new HySID("P" + m_ulPrimNo.ToString() + DateTime.Now.Second.ToString() + "-" + ((long)eKind).ToString() + sStr);

            m_csFromPortID = new HySID("");
            m_csToPortID = new HySID("");

            //バージョン情報設定
            SetNowVersion();
        }

        //======================================
        // 表示用情報関連メソッド
        //======================================

        /// <summary><para>method outline:</para>
        /// <para>描画位置設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetPosition( lX, lY )</para>
        /// </example>
        /// <param name="lX">描画位置(X)</param>
        /// <param name="lY">描画位置(Y)</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void SetPosition(long lX, long lY)
        {
            m_lX = lX;
            m_lY = lY;
        }
        /// <summary><para>method outline:</para>
        /// <para>描画位置取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>GetPosition( ref lX, ref lY )</para>
        /// </example>
        /// <param name="lX">描画位置(X)</param>
        /// <param name="lY">描画位置(Y)</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void GetPosition(ref long lX, ref long lY)
        {
            lX = m_lX;
            lY = m_lY;
        }

        /// <summary><para>method outline:</para>
        /// <para>描画位置設定(回転)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetConnectDirection( lRotate )</para>
        /// </example>
        /// <param name="lDirection">描画位置(上：０、右：９０、下：１８０、左：２７０)</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void SetConnectDirection(long lDirection)
        {
            m_lRotate = lDirection;
        }
        /// <summary><para>method outline:</para>
        /// <para>描画位置取得(回転)</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = GetConnectDirection()</para>
        /// </example>
        /// <returns>描画位置(回転)</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public long GetConnectDirection()
        {
            return m_lRotate;
        }

        //======================================
        // 各種識別情報関連メソッド
        //======================================

        /// <summary><para>method outline:</para>
        /// <para>シンボル描画種別取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McDefine.SymbolDrawKind eDrawKind = GetSymbolDrawKind()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>シンボル描画種別</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public McDefine.SymbolDrawKind GetSymbolDrawKind()
        {
            return m_eDrawKind;
        }

        /// <summary><para>method outline:</para>
        /// <para>ID設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetID(csID)</para>
        /// </example>
        /// <param name="csID">ID</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void SetID(HySIdentifier csID)
        {
            m_csID = csID;
        }
        /// <summary><para>method outline:</para>
        /// <para>ID取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySIdentifier csIdentifier = GetID()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>HySIdentifier : ID</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual HySIdentifier GetID()
        {
            return m_csID;
        }
        /// <summary><para>method outline:</para>
        /// <para>ID一致判定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = Equal( csID )</para>
        /// </example>
        /// <param name="csID">ID</param>
        /// <returns>bool true:一致，false:不一致</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool Equal(HySIdentifier csID)
        {
            if (csID == null || m_csID == null)
            {// パラメータ,メンバ変数異常
                return false;
            }

            return m_csID.Equals(csID);
        }

        /// <summary><para>method outline:</para>
        /// <para>自身を持つ要素ID設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetElmID( csElmID )</para>
        /// </example>
        /// <param name="csElmID">自身を持つ要素ID</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public void SetElmID(HySIdentifier csElmID)
        {
            m_csElmID = csElmID;
        }
        /// <summary><para>method outline:</para>
        /// <para>自身を持つ要素ID取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySIdentifier csIdentifier = GetElmID()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>自身を持つ要素ID</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public HySIdentifier GetElmID()
        {
            return m_csElmID;
        }

        //======================================
        // 接続情報関連メソッド
        //======================================

        /// <summary><para>method outline:</para>
        /// <para>端子接続ID設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetPortID( csFromID, csToID )</para>
        /// </example>
        /// <param name="csFromID">接続元ID</param>
        /// <param name="csToID">接続先ID</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void SetPortID(HySIdentifier csFromID, HySIdentifier csToID)
        {
            m_csFromPortID = csFromID;
            m_csToPortID = csToID;
        }

        /// <summary><para>method outline:</para>
        /// <para>端子接続ID取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>GetPortID( ref csFromID, ref csToID )</para>
        /// </example>
        /// <param name="csFromID">接続元ID</param>
        /// <param name="csToID">接続先ID</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void GetPortID(ref HySIdentifier csFromID, ref HySIdentifier csToID)
        {
            csFromID = m_csFromPortID;
            csToID = m_csToPortID;
        }


        //======================================
        // 構造定義ファイル入出力関連メソッド
        //======================================

        /// <summary><para>method outline:</para>
        /// <para>構造定義ＸＭＬ入力</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReadStructureBody( csXml, csMdlFctry )</para>
        /// </example>
        /// <param name="csXml">入力ＸＭＬ</param>
        /// <param name="csMdlFctry">モデルファクトリクラス</param>
        /// <returns>true</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool ReadStructureBody(HySXmlNode csXml, McModelFactorySet csMdlFctry)
        {
            string sDirection = csXml.GetAttribute(McDefine.xml_DIRECTION);
            if (sDirection != "") { m_lRotate = long.Parse(sDirection); }
            string sX = csXml.GetAttribute(McDefine.xml_X);
            if (sX != "") { m_lX = long.Parse(sX); }
            string sY = csXml.GetAttribute(McDefine.xml_Y);
            if (sY != "") { m_lY = long.Parse(sY); }

            return true;
        }
        /// <summary><para>method outline:</para>
        /// <para>構造定義ファイル本体部出力</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>HySXmlNode csNode = WriteStructureBody( ref csXmlWriter )</para>
        /// </example>
        /// <param name="csXmlWriter">XMLファイル書き出しクラス</param>
        /// <returns>XMLノードクラス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal virtual HySXmlNode WriteStructureBody(ref HySXmlWriter csXmlWriter)
        {
            HySXmlNode csRtnNode = null;
            if (m_eDrawKind == McDefine.SymbolDrawKind.HYM_RECEIVE)
            {
                // ReceivePortタグ
                csRtnNode = HySXmlNode.CreateElement(McDefine.xml_RECEIVE_PORT, csXmlWriter);
            }
            else if (m_eDrawKind == McDefine.SymbolDrawKind.HYM_SEND)
            {
                // SendPortタグ
                csRtnNode = HySXmlNode.CreateElement(McDefine.xml_SEND_PORT, csXmlWriter);
            }
            csRtnNode.SetAttribute(McDefine.xml_ID, m_csID.GetString().ToString());
            csRtnNode.SetAttribute(McDefine.xml_DIRECTION, m_lRotate.ToString());
            csRtnNode.SetAttribute(McDefine.xml_X, m_lX.ToString());
            csRtnNode.SetAttribute(McDefine.xml_Y, m_lY.ToString());
            return csRtnNode;
        }

        /// <summary><para>method outline:</para>
        /// <para>一貫番号取得</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>ulong ulRtn = GetPrimNo()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>一貫番号</returns>
        /// <exception cref="">無し</exception>
        /// <remarks>
        /// <para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        static public ulong GetPrimNo()
        {
            return m_ulPrimNo;
        }

        /// <summary><para>method outline:</para>
        /// <para>全削除</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Free()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal virtual void Free()
        {
            m_csID = null;
            m_csElmID = null;
            m_csFromPortID = null;
            m_csToPortID = null;
        }

        /// <summary><para>method outline:</para>
        /// <para>情報のコピー</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>CopyInf(csOrgPort)</para>
        /// </example>
        /// <param name="csOrgPort">コピー元</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void CopyInf(McStructPort csOrgPort)
        {
        }

        /// <summary><para>method outline:</para>
        /// <para>内部に含まれる部品のIDを変更する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> ChangeID() </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>接続線、ポートのID含む</para>
        /// </remarks>
        internal virtual HySID ChangeID()
        {
            // 自身のID設定
            McStructPort.m_ulPrimNo += 1;

            string sStr = DateTime.Now.Minute.ToString() + DateTime.Now.Hour.ToString()
                         + "-" + DateTime.Now.Day.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Year.ToString();
            //m_csID = new HySID("P" + m_ulPrimNo.ToString() + DateTime.Now.Second.ToString() + "-", ((long)McDefine.SymbolDrawKind.HYM_SEND).ToString(), sStr);
            m_csID = new HySID("P" + m_ulPrimNo.ToString() + DateTime.Now.Second.ToString() + "-" + ((long)McDefine.SymbolDrawKind.HYM_SEND).ToString() + sStr);

            return m_csID as HySID;
        }


        // ================================================
        //   Undo/Redo用処理
        // ================================================
        /// <summary><para>method outline:</para>
        /// <para>情報のコピー</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>McStructPort csStructPort = CopyInfUsedByUndoRedoOnly(csCopyElement)</para>
        /// </example>
        /// <param name="csCopyElement">複製要素</param>
        /// <returns>McStructPort 複製要素</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>GUIでのUndo/Redoのみ使用、その他は使用禁止</para>
        /// </remarks>
        public virtual McStructPort CopyInfUsedByUndoRedoOnly(McStructPort csCopyElement)
        {
            if (csCopyElement == null)
            {
                csCopyElement = new McStructPort(m_eDrawKind);
            }

            McStructPort.m_ulPrimNo -= 1;

            csCopyElement.m_eDrawKind = m_eDrawKind;
            csCopyElement.m_csID = m_csID;
            csCopyElement.m_csElmID = m_csElmID;
            csCopyElement.m_csFromPortID = m_csFromPortID;
            csCopyElement.m_csToPortID = m_csToPortID;
            csCopyElement.m_lX = m_lX;
            csCopyElement.m_lY = m_lY;
            csCopyElement.m_lRotate = m_lRotate;

            return csCopyElement;
        }

        /*
        /// <summary>接続元端子ID</summary>
        virtual public HySIdentifier GetFromPortID()
        { return m_csFromPortID; }
        /// <summary>接続先端子ID</summary>
        virtual public HySIdentifier GetToPortID()
        { return m_csToPortID; }
        */

        // ================================================
        //   バージョンアップ時の下位互換性を保つ為の処理
        // ================================================
        /// <summary>保存バージョン情報</summary>
        private string m_sDecodedVersion;

        /// <summary><para>method outline:</para>
        /// <para>バージョン情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sDecodedVersion = GetDecodedVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>string 保存バージョン情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>メンバー変数に設定されているバージョン情報を返す</para>
        /// </remarks>
        public string GetDecodedVersion()
        {
            return m_sDecodedVersion;
        }

        /// <summary><para>method outline:</para>
        /// <para>バージョン情報取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> string sVersion = GetNowVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>string 現在のバージョン情報</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public string GetNowVersion()
        {
            return "1.00";
        }

        /// <summary><para>method outline:</para>
        /// <para>バージョン情報設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> SetNowVersion()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>現在のバージョン情報をメンバー変数に設定する</para>
        /// </remarks>
        public void SetNowVersion()
        {
            m_sDecodedVersion = GetNowVersion();
        }

        /// <summary><para>method outline:</para>
        /// <para>復元後の整合性確保処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> PostDeserialize( ) </para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>シリアライズされた旧バージョン情報を復元する際、過去の整合性をとる時に使用する
        /// バージョンによって変数等追加がない場合には、実装の必要がない
        /// </para>
        /// </remarks>
        public virtual void PostDeserialize()
        {
            if (GetDecodedVersion() != GetNowVersion())
            {
                //旧バージョンから順にバージョンを上げて行く
                switch (GetDecodedVersion())
                {
                    case "1.00":
                        break;
                }
                SetNowVersion();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>逆シリアル化時追加処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> IDeserializationCallback.OnDeserialization(csObj)</para>
        /// </example>
        /// <param name="csObj">ダミー</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>予約処理</para>
        /// </remarks>
        void IDeserializationCallback.OnDeserialization(Object csObj)
        {
            PostDeserialize();
        }
    }
}
