﻿// ==========================================================================
//  Squidex Headless CMS
// ==========================================================================
//  Copyright (c) Squidex UG (haftungsbeschraenkt)
//  All rights reserved. Licensed under the MIT license.
// ==========================================================================

using Squidex.Infrastructure.EventSourcing;

namespace Squidex.Infrastructure.States
{
    internal sealed class BatchPersistence<T> : IPersistence<T>
    {
        private readonly DomainId ownerKey;
        private readonly BatchContext<T> context;
        private readonly IReadOnlyList<Envelope<IEvent>> events;
        private readonly HandleEvent? applyEvent;

        public long Version { get; }

        public bool IsSnapshotStale => false;

        internal BatchPersistence(DomainId ownerKey, BatchContext<T> context, long version, IReadOnlyList<Envelope<IEvent>> @events,
            HandleEvent? applyEvent)
        {
            this.ownerKey = ownerKey;
            this.context = context;
            this.events = events;
            this.applyEvent = applyEvent;

            Version = version;
        }

        public Task DeleteAsync()
        {
            throw new NotSupportedException();
        }

        public Task WriteEventsAsync(IReadOnlyList<Envelope<IEvent>> events)
        {
            throw new NotSupportedException();
        }

        public Task ReadAsync(long expectedVersion = -2)
        {
            if (applyEvent != null)
            {
                foreach (var @event in events)
                {
                    if (!applyEvent(@event))
                    {
                        break;
                    }
                }
            }

            if (expectedVersion > EtagVersion.Any && expectedVersion != Version)
            {
                if (Version == EtagVersion.Empty)
                {
                    throw new DomainObjectNotFoundException(ownerKey.ToString()!);
                }
                else
                {
                    throw new InconsistentStateException(Version, expectedVersion);
                }
            }

            return Task.CompletedTask;
        }

        public Task WriteSnapshotAsync(T state)
        {
            context.Add(ownerKey, state, Version);

            return Task.CompletedTask;
        }
    }
}
