using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using InABox.Core;

namespace InABox.Core
{
    public class DFLayoutEmbeddedMediaValues : IEnumerable<DFLayoutEmbeddedMediaValue>, INotifyPropertyChanged, IDFLayoutValue<List<DFLayoutEmbeddedMediaValue>>
    {
        private readonly List<DFLayoutEmbeddedMediaValue> _values = new List<DFLayoutEmbeddedMediaValue>();
        public DFLayoutEmbeddedMediaValue[] Values => _values.ToArray();

        public bool Present { get; set; } = false;

        public List<byte[]> AsByteArrays
        {
            get => _values.Select(x => x?.Data).OfType<byte[]>().ToList();
            set
            {
                _values.Clear();
                foreach (var bytes in value)
                    _values.Add(new DFLayoutEmbeddedMediaValue() { ID = Guid.Empty, Data = bytes});
                OnPropertyChanged(nameof(Values));
            }
        }

        public void Serialize(DFSaveStorageEntry storage)
        {
            var results = new List<string>();
            foreach (var value in _values)
                results.Add(Serialization.Serialize((value.ID, value.Thumbnail)));
            if (results.Any())
                storage.SetBlobValue(results);
        }

        public void Deserialize(DFLoadStorageEntry storage)
        {
            _values.Clear();
            Present = storage.HasValue();
            if (Present)
            {
                var values = storage.GetValue<string[]>() ?? Array.Empty<string>();
                foreach (string s in values)
                {
                    if (!s.IsNullOrWhiteSpace())
                    {
                        var externaldata = Serialization.Deserialize<(Guid, byte[])>(s);
                        if (externaldata.Item1 != Guid.Empty)
                        {
                            _values.Add(new DFLayoutEmbeddedMediaValue()
                            {
                                ID = externaldata.Item1,
                                Thumbnail = externaldata.Item2
                            });
                        }
                    }
                }
            }
        }
        
        public IEnumerator<DFLayoutEmbeddedMediaValue> GetEnumerator() => _values.GetEnumerator();

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

        public void Add(DFLayoutEmbeddedMediaValue value)
        {
            _values.Add(value);
            OnPropertyChanged(nameof(Values));
        }

        public void Remove(DFLayoutEmbeddedMediaValue value)
        {
            if (_values.Contains(value))
            {
                _values.Remove(value);
                OnPropertyChanged(nameof(Values));
            }
        }

        public void Clear()
        {
            _values.Clear();
            OnPropertyChanged(nameof(Values));
        }

        public event PropertyChangedEventHandler? PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }
    }
}