using System;
using System.Diagnostics;

namespace Aitex.Core.RT.IOCore
{
	public abstract class IOAccessor<T>: IIOAccessor where T: unmanaged
	{
		#region Variables

        
		private readonly string _name;
		private readonly IOType _type;
		private readonly string _addr;
		private readonly int _index;
        protected readonly bool IsSimulator;
        protected T[] Buffer;

		#endregion

		#region Constructors

		public IOAccessor(string name, int index, string address, IOType type, bool isSimulator, bool disImmCache)
		{
            IsSimulator = isSimulator;
			_name = name;
			_index = index;
			_addr = address;
			_type = type;
			DisableImmediatelyCache = disImmCache;
		}

		#endregion

		public object NonTypedValue => Value;
		
		/// <summary>
		/// 返回当前IO的值。
		/// </summary>
		public T Value
		{
			get => GetValue(BlockOffset);
			set => SetValue(BlockOffset, value);
		}

		public string Name => _name;

		public IOType Type => _type;
		
		public int Index => _index;

		public int BlockIndex { get; set; }

		public int BlockOffset { get; set; }

		public string Addr => _addr;

		public string Provider { get; set; }

		public bool Visible { get; set; }

		public string Description { get; set; }

		public string StringIndex => _name.Substring(0, 2) + "-" + _index;

		public int IoTableIndex { get; set; }

		public bool DisableImmediatelyCache { get; }

		#region Methods

		protected virtual T GetValue(int offset)
		{
			Debug.Assert(Buffer != null && offset >= 0 && offset < Buffer.Length);
			return Buffer[offset];
		}

		protected virtual void SetValue(int offset, T value)
		{
			Debug.Assert(Buffer != null && offset >= 0 && offset < Buffer.Length);
			Buffer[offset] = value;
		}


		/// <inheritdoc />
		public void BindBuffer(object buff)
		{
			Buffer = (T[])Convert.ChangeType(buff, typeof(T[]));
		}
		
		/// <inheritdoc />
		public override string ToString()
		{
			return $"{Name}";
		}

		#endregion
	}
}
