﻿// 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.

#nullable enable

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Diagnostics;
using Apache.Arrow.Arrays;
using Apache.Arrow.Types;

namespace Apache.Arrow
{
    public class Decimal256Array : FixedSizeBinaryArray, IReadOnlyList<SqlDecimal?>, IReadOnlyList<string?>
    {
        public class Builder : BuilderBase<Decimal256Array, Builder>
        {
            public Builder(Decimal256Type type) : base(type, 32)
            {
                DataType = type;
            }

            protected new Decimal256Type DataType { get; }

            protected override Decimal256Array Build(ArrayData data)
            {
                return new Decimal256Array(data);
            }

            public Builder Append(decimal value)
            {
                Span<byte> bytes = stackalloc byte[DataType.ByteWidth];
                DecimalUtility.GetBytes(value, DataType.Precision, DataType.Scale, DataType.ByteWidth, bytes);

                return Append(bytes);
            }

            public Builder AppendRange(IEnumerable<decimal> values)
            {
                if (values == null)
                {
                    throw new ArgumentNullException(nameof(values));
                }

                foreach (decimal d in values)
                {
                    Append(d);
                }

                return Instance;
            }

            public Builder Append(string value)
            {
                if (value == null)
                {
                    AppendNull();
                }
                else
                {
                    Span<byte> bytes = stackalloc byte[DataType.ByteWidth];
                    DecimalUtility.GetBytes(value, DataType.Precision, DataType.Scale, ByteWidth, bytes);
                    Append(bytes);
                }

                return Instance;
            }

            public Builder AppendRange(IEnumerable<string> values)
            {
                if (values == null)
                {
                    throw new ArgumentNullException(nameof(values));
                }

                foreach (string s in values)
                {
                    Append(s);
                }

                return Instance;
            }

            public Builder Append(SqlDecimal value)
            {
                Span<byte> bytes = stackalloc byte[DataType.ByteWidth];
                DecimalUtility.GetBytes(value, DataType.Precision, DataType.Scale, bytes);
                if (!value.IsPositive)
                {
                    var span = bytes.CastTo<long>();
                    span[2] = -1;
                    span[3] = -1;
                }

                return Append(bytes);
            }

            public Builder AppendRange(IEnumerable<SqlDecimal> values)
            {
                if (values == null)
                {
                    throw new ArgumentNullException(nameof(values));
                }

                foreach (SqlDecimal d in values)
                {
                    Append(d);
                }

                return Instance;
            }

            public Builder Set(int index, decimal value)
            {
                Span<byte> bytes = stackalloc byte[DataType.ByteWidth];
                DecimalUtility.GetBytes(value, DataType.Precision, DataType.Scale, DataType.ByteWidth, bytes);

                return Set(index, bytes);
            }
        }

        public Decimal256Array(ArrayData data)
            : base(ArrowTypeId.Decimal256, data)
        {
            data.EnsureDataType(ArrowTypeId.Decimal256);
            data.EnsureBufferCount(2);
            Debug.Assert(Data.DataType is Decimal256Type);
        }
        public override void Accept(IArrowArrayVisitor visitor) => Accept(this, visitor);

        public int Scale => ((Decimal256Type)Data.DataType).Scale;
        public int Precision => ((Decimal256Type)Data.DataType).Precision;
        public int ByteWidth => ((Decimal256Type)Data.DataType).ByteWidth;

        public decimal? GetValue(int index)
        {
            if (IsNull(index))
            {
                return null;
            }

            return DecimalUtility.GetDecimal(ValueBuffer, Offset + index, Scale, ByteWidth);
        }

        public IList<decimal?> ToList(bool includeNulls = false)
        {
            var list = new List<decimal?>(Length);

            for (int i = 0; i < Length; i++)
            {
                decimal? value = GetValue(i);

                if (value.HasValue)
                {
                    list.Add(value.Value);
                }
                else
                {
                    if (includeNulls)
                    {
                        list.Add(null);
                    }
                }
            }

            return list;
        }

        public string? GetString(int index)
        {
            if (IsNull(index))
            {
                return null;
            }
            return DecimalUtility.GetString(ValueBuffer, Offset + index, Precision, Scale, ByteWidth);
        }

        public bool TryGetSqlDecimal(int index, out SqlDecimal? value)
        {
            if (IsNull(index))
            {
                value = null;
                return true;
            }

            const int longWidth = 4;
            var span = ValueBuffer.Span.CastTo<long>().Slice((Offset + index) * longWidth);
            if ((span[2] == 0 && span[3] == 0) ||
                (span[2] == -1 && span[3] == -1))
            {
                value = DecimalUtility.GetSqlDecimal128(ValueBuffer, 2 * (Offset + index), Precision, Scale);
                return true;
            }

            value = null;
            return false;
        }

        private SqlDecimal? GetSqlDecimal(int index)
        {
            SqlDecimal? value;
            if (TryGetSqlDecimal(index, out value))
            {
                return value;
            }

            throw new OverflowException("decimal256 value out of range of SqlDecimal");
        }

        int IReadOnlyCollection<SqlDecimal?>.Count => Length;
        SqlDecimal? IReadOnlyList<SqlDecimal?>.this[int index] => GetSqlDecimal(index);

        IEnumerator<SqlDecimal?> IEnumerable<SqlDecimal?>.GetEnumerator()
        {
            for (int index = 0; index < Length; index++)
            {
                yield return GetSqlDecimal(index);
            }
        }

        int IReadOnlyCollection<string?>.Count => Length;
        string? IReadOnlyList<string?>.this[int index] => GetString(index);

        IEnumerator<string?> IEnumerable<string?>.GetEnumerator()
        {
            for (int index = 0; index < Length; index++)
            {
                yield return GetString(index);
            }
        }

        IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<string?>)this).GetEnumerator();
    }
}
