using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Runtime.InteropServices;

namespace Post
{
    public class Struct
    {
        #region acdsn
        [StructLayout(LayoutKind.Sequential)]
        [Serializable]
        public class ACDSN
        {
            public UInt32 high;
            public UInt32 wrap;
            public UInt32 base_n;
            public ACDSN()
            {
                high = 0;
                wrap = 0;
                base_n = 0;
            }
            public ACDSN(UInt32 high, UInt32 wrap, UInt32 base_n)
            {
                this.high = high;
                this.wrap = wrap;
                this.base_n = base_n;
            }
        }
        #endregion

        #region Timespec
        [StructLayout(LayoutKind.Sequential)]
        [Serializable]
        public class Timespec
        {
            public ulong tv_sec;     // seconds
            public ulong tv_nsec;     // nanoseconds
            public Timespec()
            {
                tv_sec = 0;
                tv_nsec = 0;
            }
            public Timespec(uint tv_sec, uint tv_nsec)
            {
                this.tv_sec = tv_sec;
                this.tv_nsec = tv_nsec;
            }
        }
        #endregion

        #region TracingRecordHeaderTransaction
        public class TracingRecordHeaderTransaction
        {
            public TracingRecordHeader header;
            public TracingRecordTransaction transaction;
            public TracingRecordHeaderTransaction()
            {
                header = new TracingRecordHeader();
                transaction = new TracingRecordTransaction();
            }
        }
        #endregion

        #region bracket
        [StructLayout(LayoutKind.Sequential)]
        public class TracingRecordBracket
        {
            public int index;
            public short flag;
            public short unused;
            public UInt32 length;
        }
        #endregion

        #region TracingDefinition
        [StructLayout(LayoutKind.Sequential)]
        public class TracingRecordDefinition
        {
            public TracingRecordHeader header;
            public TracingRecordDataDefinition data;
            public TracingRecordTransaction transaction;
            public TracingRecordDefinition()
            {
                header = new TracingRecordHeader();
                data = new TracingRecordDataDefinition();
                transaction = new TracingRecordTransaction();
            }
        }
        [StructLayout(LayoutKind.Sequential)]
        public class TracingRecordDataDefinition
        {
            public TracingRecordDataDefinitionTable table_def;
            public List<TracingRecordDataDefinitionColumn> column_def;
            public TracingRecordDataDefinition()
            {
                table_def = new TracingRecordDataDefinitionTable();
                column_def = new List<TracingRecordDataDefinitionColumn>();
            }
        }
        [StructLayout(LayoutKind.Sequential)]
        public class TracingRecordDataDefinitionTable
        {
            public short definition_id;
            public short num_columns;
            public short num_key_columns;
            public short num_use_columns;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)]
            public string table_name;
        }
        [StructLayout(LayoutKind.Sequential)]
        public class TracingRecordDataDefinitionColumn
        {
            public UInt16 col_no;
            public UInt16 segcol_no;
            public UInt16 internal_no;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string name;
            public byte datatype;
            public byte sub_datatype;
            public UInt16 native_datatype;
            public UInt16 extern_length;
            public UInt16 internal_length;
            public byte is_nullable;
            public byte is_hidden;
            public byte key_column;
            public UInt16 precision;
            public UInt16 scale;
            public UInt64 property;
            public UInt32 character_set;
            public byte is_lob;
        }
        #endregion

        #region TracingRecordHeader
        [StructLayout(LayoutKind.Sequential)]
        public class TracingRecordHeader
        {
            public byte command;  // DML, DDL
            public byte trc_record_type;         // 0x01 DELETE, 0x02 INSERT, 0x03 UPDATE, 0x07 UPDATE including PK
            public byte capture_type;    // fetch, redo 추출 타입
            public byte partition;   // bulk 구분
            public Int32 length;     // data 데이터의 크기
            public Timespec timestamp;
            public byte redo_thread_node;    // thread#
            public Int32 redo_sequence;       // RBA
            public Int32 redo_block;         // RBA
            public Int32 redo_offset;         // RBA
            public UInt32 tx_index;    // 트랜젝션내에서의 내 순번
            public byte tx_indicator;     // 트랜젝션 지시자, 트랜젝션에서의 현재
            public Int16 record_columns;     // 컬럼 갯수
            public byte record_continued;    // 레코드 이어지는 여부, Y/N
            public UInt32 record_count;  // lob 레코드 순번
            public Int16 definition_id;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)]
            public string schema;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)]
            public string object_n;
            public TracingRecordHeader()
            {
                timestamp = new Timespec();
            }
        }
        #endregion

        #region TracingRecordTransaction
        [StructLayout(LayoutKind.Sequential)]
        public class TracingRecordTransaction
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
            public string rowid;
            public ACDSN commit_dsn;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
            public string tx_id;
            public TracingRecordTransaction()
            {
                commit_dsn = new ACDSN();
            }
        }
        #endregion

        #region tracing_file_header
        [StructLayout(LayoutKind.Sequential)]
        public class TracingFileHeader
        {
            public TracingMeta meta;
            public TracingExtract extract;
            public TracingOs os;
            public TracingDatabase db;
            public TracingFileHeader()
            {
                meta = new TracingMeta();
                extract = new TracingExtract();
                os = new TracingOs();
                db = new TracingDatabase();
            }
        }
        [StructLayout(LayoutKind.Sequential)]
        public class TracingMeta
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
            public byte[] version_signature;    // signature            
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
            public string version;     // tracing version            
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
            public string pad2;
            public UInt32 cksum;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string alias;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string pad3;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string filename;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 196)]
            public string pad4;
        }
        [StructLayout(LayoutKind.Sequential)]
        public class TracingExtract
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string alias;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string pad1;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string version;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string pad2;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
            public string begin_timestamp;
            public ACDSN begin_commit_dsn;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
            public string pad3;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string pad4;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
            public string end_timestamp;
            public ACDSN end_commit_dsn;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
            public string pad5;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string pad6;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
            public string pad7;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string pad8;
            public TracingExtract()
            {
                begin_commit_dsn = new ACDSN();
                end_commit_dsn = new ACDSN();
            }
        }
        [StructLayout(LayoutKind.Sequential)]
        public class TracingOs
        {
            public byte type;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
            public string pad1;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
            public string pad2;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string osname;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string hostname;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string kernel_release;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
            public string kernel_version;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
            public string pad3;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string architecture;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 96)]
            public string pad4;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string pad5;
        }
        [StructLayout(LayoutKind.Sequential)]
        public class TracingDatabase
        {
            public byte type;                       // DBTYPE_ORACLE
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
            public string pad1;
            public byte version_flag;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
            public string pad2;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string db_name;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string instance_name;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
            public string pad3;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
            public string version;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
            public string pad4;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 384)]
            public string banner;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
            public string pad5;
        }
        #endregion

        #region TracingRecordBuffer
        [StructLayout(LayoutKind.Sequential)]
        public class TracingRecordBuffer
        {
            public TracingRecordBracket opener;
            public byte[] data;
            public TracingRecordBracket closer;
        }
        #endregion

        #region tracing_record : dml    
        [StructLayout(LayoutKind.Sequential)]
        public class TracingRecordDml
        {
            public TracingRecordHeader header;
            public List<TracingRecordData> dataList;
            public TracingRecordTransaction transaction;
            public TracingRecordDml()
            {
                header = new TracingRecordHeader();
                dataList = new List<TracingRecordData>();
                transaction = new TracingRecordTransaction();
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public class TracingRecordData
        {
            public Int16 colno;
            public byte flag;                   // 0x01 BEFORE, 0x02 AFTER
            public Int16 type;                 // 0x01 NUMERIC, 0x02 STRING, 0x03 DATE
            public byte is_null;
            public UInt32 length;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5000)]
            public string str;
            public byte[] bytes;
        }
        #endregion

        #region TraceDml : dml 정보 구조체 - post 로직 사용을 위한 구조체
        public class TraceDml
        {
            public byte trc_record_type;
            public byte partition;
            public string container;
            public string schema;
            public string object_n;
            public string updatemask;
            public List<Struct.TracingRecordDml> tracingRecordList;
            public TraceDml()
            {
                tracingRecordList = new List<Struct.TracingRecordDml>();
            }
        }
        #endregion

    }
}