using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Quadarax.Foundation.QConsole.Value
{
    public abstract class AbstractValue
    {
        private object _value;

        /// <summary>
        /// Defines if value is set. Not null.
        /// </summary>
        public bool HasValue => _value != null;

        /// <summary>
        /// Returns underlying system value type.
        /// </summary>
        public Type ValueType { get; }

        public AbstractValue()
        {
            Reset();
        }

        public AbstractValue(Type valueType, object value) : this(valueType)
        {
            _value = value;
        }
        protected AbstractValue(Type valueType)
        {
            ValueType = valueType ?? throw new ArgumentNullException(nameof(valueType));
        }

        protected abstract object ConvertStringToValue(string valueAsString);

        public abstract string AsString();

        public void Set(string valueAsString)
        {
            if (string.IsNullOrEmpty(valueAsString))
            {
                Reset();
                return;
            }
            Set(ConvertStringToValue(valueAsString));
        }

        public virtual void Set(object value)
        {
            _value = value;
        }

        public object Get()
        {
            return _value;
        }

        public void Reset()
        {
            _value = null;
        }

        public static AbstractValue Create(TypeValuesEnum typeValue)
        {
            switch (typeValue)
            {
                case TypeValuesEnum.Bool:
                    return new BoolValue();
                case TypeValuesEnum.Date:
                    return new DateValue();
                case TypeValuesEnum.DateTime:
                    return new DateTimeValue();
                case TypeValuesEnum.Decimal:
                    return new DecimalValue();
                case TypeValuesEnum.Guid:
                    return new GuidValue();
                case TypeValuesEnum.Integer:
                    return new IntegerValue();
                case TypeValuesEnum.String:
                    return new StringValue();
                case TypeValuesEnum.Time:
                    return new TimeValue();
                default:
                    throw new NotSupportedException($"Unsupported argument value '{typeValue}'");
            }
        }

        public override string ToString()
        {
            return AsString();
        }
    }
}
