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

namespace Project
{
    public class CInterLock
    {
        UInt64 offsetValue = 0x01;
        public object Tag { get; set; }
        public string errorMessage;
        protected UInt64 _value;

        public UInt64 Value { get { return _value; } set { _value = value; } }

        public event EventHandler<ValueEventArgs> ValueChanged;
        public class ValueEventArgs : EventArgs
        {
            private int _arridx;
            private Boolean _oldvalue;
            private Boolean _newvalue;
            private string _reason;

            public int ArrIDX { get { return _arridx; } }
            public Boolean OldValue { get { return _oldvalue; } }
            public Boolean NewValue { get { return _newvalue; } }
            public string Reason { get { return _reason; } }
            public Boolean NewOn { get; set; }
            public Boolean NewOff { get; set; }

            public ValueEventArgs(int arridx, Boolean oldvalue, Boolean newvalue, string reason_, Boolean newon_, Boolean newof_)
            {
                _arridx = arridx;
                _oldvalue = oldvalue;
                _newvalue = newvalue;
                _reason = reason_;
                this.NewOn = newon_;
                this.NewOff = newon_;
            }
        }

        public CInterLock(object tag = null)
        {
            errorMessage = string.Empty;
            _value = 0;
            this.Tag = tag;
        }

        public Boolean get(int idx)
        {
			if (idx >= 64)
				throw new Exception("flag는 최대 64개를 지원 합니다");

            var offset = (UInt64)(offsetValue << idx);
            return (_value & offset) != 0;
        }
        public void set(int idx, Boolean value, string reason)
        {
			if (idx >= 64)
				throw new Exception("flag는 최대 64개를 지원 합니다");

			var oldvalue = get(idx);
            var raw_old = _value;
            if (value)
            {
                var offset = (UInt64)(offsetValue << idx);
                _value = _value | offset;
            }
            else
            {
                var shiftvalue = (UInt64)(offsetValue << idx);
                UInt64 offset = ~shiftvalue;
                _value = _value & offset;
            }

            if (oldvalue != value)
            {
                Boolean NewOn = (raw_old == 0 && _value > 0);
                Boolean NewOf = (raw_old != 0 && _value == 0);
                if (ValueChanged != null)
                    ValueChanged(this, new ValueEventArgs(idx, oldvalue, value, reason, NewOn, NewOf));
            }
            else
            {
                //Pub.log.Add(" >> SKIP");
                //if (string.IsNullOrEmpty(reason) == false)
                //Pub.log.Add("#### FLAG변경(값이 같아서 처리 안함) : idx=" + idx.ToString() + ",값:" + value.ToString() + ",사유:" + reason);
            }
        }
        public void Toggle(int idx, string reason = "")
        {
            var curValue = get(idx);
            set(idx, !curValue, reason);
        }

    }
}
