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

namespace VIZ.Framework.Core
{
    /// <summary>
    /// 保持符号辅助类
    /// </summary>
    public class KeepSymbolHelper
    {
        /// <summary>
        /// 参照队列长度
        /// </summary>
        /// <param name="queueLength">参照值队列长度</param>
        /// <param name="confidenceLength">置信数据长度</param>
        public KeepSymbolHelper(int queueLength, int confidenceLength)
        {
            if (queueLength <= 0)
                throw new ArgumentException(nameof(queueLength));

            if (confidenceLength <= 0 || confidenceLength > queueLength)
                throw new ArgumentException(nameof(confidenceLength));

            this.QueueLength = queueLength;
            this.ConfidenceLength = confidenceLength;
        }

        /// <summary>
        /// 参照值队列长度
        /// </summary>
        private System.Collections.Concurrent.ConcurrentQueue<double> queue = new System.Collections.Concurrent.ConcurrentQueue<double>();

        /// <summary>
        /// 参照队列长度
        /// </summary>
        public int QueueLength { get; private set; }

        /// <summary>
        /// 置信数据长度
        /// </summary>
        public int ConfidenceLength { get; private set; }

        /// <summary>
        /// 之前的符号值
        /// </summary>
        private int prevSymbol;

        /// <summary>
        /// 获取符号
        /// </summary>
        /// <param name="value">值</param>
        /// <returns>符号 （1 or -1）</returns>
        public int GetSymbol(double value)
        {
            int symbol = value > 0 ? 1 : -1;

            this.queue.Enqueue(value);
            if (this.queue.Count < this.ConfidenceLength)
            {
                this.prevSymbol = symbol;
                return symbol;
            }

            if (this.queue.Count > this.QueueLength)
            {
                this.queue.TryDequeue(out _);
            }

            int count = this.queue.Count(p => (p > 0 ? 1 : -1) == symbol);
            if (count > this.ConfidenceLength)
            {
                this.prevSymbol = symbol;
                return symbol;
            }

            return this.prevSymbol;
        }
    }
}
