/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Thrift;

namespace Apache.IoTDB.DataStructure
{
    public class SessionDataSet : System.IDisposable, System.IAsyncDisposable
    {
        private readonly long _queryId;
        private readonly long _statementId;
        private readonly string _sql;
        private readonly List<string> _columnNames;
        private readonly Dictionary<string, int> _columnNameIndexMap;
        private readonly List<string> _columnTypeLst;
        private Client _client;
        private bool _isClosed = false;
        private bool disposedValue;
        private RpcDataSet _rpcDataSet;
        private string _zoneId;
        private readonly ConcurrentClientQueue _clientQueue;

        private string TimestampStr => "Time";
        private int StartIndex => 2;
        private int Flag => 0x80;
        private int DefaultTimeout => 10000;
        public int FetchSize { get; set; }
        public SessionDataSet(
            string sql, List<string> ColumnNameList, List<string> ColumnTypeList,
            Dictionary<string, int> ColumnNameIndexMap, long QueryId, long statementId, Client client, List<byte[]> QueryResult,
            bool IgnoreTimeStamp, bool MoreData, string zoneId, List<int> ColumnIndex2TsBlockColumnIndexList, ConcurrentClientQueue clientQueue
        )
        {
            _client = client;
            _sql = sql;
            _queryId = QueryId;
            _statementId = statementId;
            _columnNameIndexMap = ColumnNameIndexMap;

            _columnNames = ColumnNameList;
            _columnTypeLst = ColumnTypeList;
            _zoneId = zoneId;
            _clientQueue = clientQueue;

            _rpcDataSet = new RpcDataSet(
                _sql, _columnNames, _columnTypeLst, _columnNameIndexMap, IgnoreTimeStamp,
                MoreData, _queryId, _statementId, _client, _client.SessionId, QueryResult, FetchSize,
                DefaultTimeout, _zoneId, ColumnIndex2TsBlockColumnIndexList
            );
        }
        [Obsolete("Use HasNextAsync() instead. This synchronous method may cause deadlocks in certain synchronization contexts.")]
        public bool HasNext() => _rpcDataSet.Next();
        public async Task<bool> HasNextAsync() => await _rpcDataSet.NextAsync().ConfigureAwait(false);
        public RowRecord Next() => _rpcDataSet.GetRow();
        public bool IsNull(string columnName) => _rpcDataSet.IsNullByColumnName(columnName);
        public bool IsNullByIndex(int columnIndex) => _rpcDataSet.IsNullByIndex(columnIndex);

        public bool GetBooleanByIndex(int columnIndex) => _rpcDataSet.GetBooleanByIndex(columnIndex);
        public bool GetBoolean(string columnName) => _rpcDataSet.GetBoolean(columnName);

        public double GetDoubleByIndex(int columnIndex) => _rpcDataSet.GetDoubleByIndex(columnIndex);
        public double GetDouble(string columnName) => _rpcDataSet.GetDouble(columnName);

        public float GetFloatByIndex(int columnIndex) => _rpcDataSet.GetFloatByIndex(columnIndex);
        public float GetFloat(string columnName) => _rpcDataSet.GetFloat(columnName);

        public int GetIntByIndex(int columnIndex) => _rpcDataSet.GetIntByIndex(columnIndex);
        public int GetInt(string columnName) => _rpcDataSet.GetInt(columnName);

        public long GetLongByIndex(int columnIndex) => _rpcDataSet.GetLongByIndex(columnIndex);
        public long GetLong(string columnName) => _rpcDataSet.GetLong(columnName);

        public object GetObjectByIndex(int columnIndex) => _rpcDataSet.GetObjectByIndex(columnIndex);
        public object GetObject(string columnName) => _rpcDataSet.GetObject(columnName);

        public string GetStringByIndex(int columnIndex) => _rpcDataSet.GetStringByIndex(columnIndex);
        public string GetString(string columnName) => _rpcDataSet.GetString(columnName);

        public DateTime GetTimestampByIndex(int columnIndex) => _rpcDataSet.GetTimestampByIndex(columnIndex);
        public DateTime GetTimestamp(string columnName) => _rpcDataSet.GetTimestamp(columnName);

        public DateTime GetDateByIndex(int columnIndex) => _rpcDataSet.GetDateByIndex(columnIndex);
        public DateTime GetDate(string columnName) => _rpcDataSet.GetDate(columnName);

        public Binary GetBlobByIndex(int columnIndex) => _rpcDataSet.GetBinaryByIndex(columnIndex);
        public Binary GetBlob(string columnName) => _rpcDataSet.GetBinary(columnName);

        public int FindColumn(string columnName) => _rpcDataSet.FindColumn(columnName);

        public IReadOnlyList<string> GetColumnNames() => _rpcDataSet._columnNameList;
        public IReadOnlyList<string> GetColumnTypes() => _rpcDataSet._columnTypeList;

        /// <summary>
        /// Gets the number of rows in the current fetched batch (tsBlock).
        /// Note: This is NOT the total row count of the query result. Use HasNext() to check for more data.
        /// </summary>
        /// <returns>The number of rows in the current batch.</returns>
        public int CurrentBatchRowCount() => _rpcDataSet._tsBlockSize;

        /// <summary>
        /// Gets the number of rows in the current fetched batch.
        /// </summary>
        /// <returns>The number of rows in the current batch.</returns>
        [Obsolete("Use CurrentBatchRowCount() instead. This method returns batch size, not total row count.")]
        public int RowCount() => _rpcDataSet._tsBlockSize;

        public void ShowTableNames()
        {
            IReadOnlyList<string> columns = GetColumnNames();
            foreach (string columnName in columns)
            {
                Console.Write($"{columnName}\t");
            }
            Console.WriteLine();
        }

        public async Task Close()
        {
            if (!_isClosed)
            {
                var req = new TSCloseOperationReq(_client.SessionId)
                {
                    QueryId = _queryId,
                    StatementId = _statementId
                };

                try
                {
                    var status = await _client.ServiceClient.closeOperationAsync(req);
                }
                catch (TException e)
                {
                    throw new TException("Operation Handle Close Failed", e);
                }
                finally
                {
                    _isClosed = true;
                    await _rpcDataSet.Close();
                    _clientQueue.Add(_client);
                    _client = null;
                }
            }
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    try
                    {
                        this.Close().Wait();
                    }
                    catch
                    {
                    }
                }
                disposedValue = true;
            }
        }

        public void Dispose()
        {
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }

        public async ValueTask DisposeAsync()
        {
            if (!disposedValue)
            {
                try
                {
                    await this.Close().ConfigureAwait(false);
                }
                catch
                {
                }
                disposedValue = true;
            }
            GC.SuppressFinalize(this);
        }
    }
}
