<commit_before>﻿using Microsoft.EntityFrameworkCore;
using Money.Data;
using Money.Services;
using Money.Services.Models.Builders;
using Neptuo;
using Neptuo.Data;
using Neptuo.Events;
using Neptuo.Formatters;
using Neptuo.Migrations;
using Neptuo.ReadModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI;

namespace Money.Bootstrap
{
    internal class UpgradeService : IUpgradeService
    {
        private readonly IDomainFacade domainFacade;
        private readonly IEventRebuilderStore eventStore;
        private readonly IFormatter eventFormatter;

        public const int CurrentVersion = 2;

        public UpgradeService(IDomainFacade domainFacade, IEventRebuilderStore eventStore, IFormatter eventFormatter)
        {
            Ensure.NotNull(domainFacade, "domainFacade");
            Ensure.NotNull(eventStore, "eventStore");
            Ensure.NotNull(eventFormatter, "eventFormatter");
            this.domainFacade = domainFacade;
            this.eventStore = eventStore;
            this.eventFormatter = eventFormatter;
        }

        public bool IsRequired()
        {
            return CurrentVersion > GetCurrentVersion();
        }

        public async Task UpgradeAsync(IUpgradeContext context)
        {
            int currentVersion = GetCurrentVersion();
            if (CurrentVersion <= currentVersion)
                return;

            context.TotalSteps(CurrentVersion - currentVersion);
            await Task.Delay(500);

            if (currentVersion < 1)
            {
                context.StartingStep(currentVersion - 0, "Creating default categories.");
                await UpgradeVersion1();
            }

            if (currentVersion < 2)
            {
                context.StartingStep(currentVersion - 1, "Rebuilding internal database.");
                await UpgradeVersion2();
            }

            ApplicationDataContainer migrationContainer = GetMigrationContainer();
            migrationContainer.Values["Version"] = CurrentVersion;
        }

        private ApplicationDataContainer GetMigrationContainer()
        {
            ApplicationDataContainer root = ApplicationData.Current.LocalSettings;

            ApplicationDataContainer migrationContainer;
            if (!root.Containers.TryGetValue("Migration", out migrationContainer))
                migrationContainer = root.CreateContainer("Migration", ApplicationDataCreateDisposition.Always);

            return migrationContainer;
        }

        private int GetCurrentVersion()
        {
            ApplicationDataContainer migrationContainer = GetMigrationContainer();
            int currentVersion = (int?)migrationContainer.Values["Version"] ?? 0;
            return currentVersion;
        }

        private async Task UpgradeVersion1()
        {
            EventSourcingContext();
            await RecreateReadModelContext();

            await domainFacade.CreateCategoryAsync("Home", Colors.SandyBrown);
            await domainFacade.CreateCategoryAsync("Food", Colors.OrangeRed);
            await domainFacade.CreateCategoryAsync("Eating Out", Colors.DarkRed);
        }

        private Task UpgradeVersion2()
        {
            return RecreateReadModelContext();
        }

        private void EventSourcingContext()
        {
            using (var eventSourcing = new EventSourcingContext())
            {
                eventSourcing.Database.EnsureDeleted();
                eventSourcing.Database.EnsureCreated();
                eventSourcing.Database.Migrate();
            }
        }

        private Task RecreateReadModelContext()
        {
            using (var readModels = new ReadModelContext())
            {
                readModels.Database.EnsureDeleted();
                readModels.Database.EnsureCreated();
            }

            // Should match with ReadModels.
            Rebuilder rebuilder = new Rebuilder(eventStore, eventFormatter);
            rebuilder.AddAll(new CategoryBuilder());
            rebuilder.AddAll(new OutcomeBuilder(domainFacade.PriceFactory));<commit_msg>Add default CZK currency to the upgrade service.<commit_after>﻿using Microsoft.EntityFrameworkCore;
using Money.Data;
using Money.Services;
using Money.Services.Models.Builders;
using Neptuo;
using Neptuo.Data;
using Neptuo.Events;
using Neptuo.Formatters;
using Neptuo.Migrations;
using Neptuo.ReadModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI;

namespace Money.Bootstrap
{
    internal class UpgradeService : IUpgradeService
    {
        private readonly IDomainFacade domainFacade;
        private readonly IEventRebuilderStore eventStore;
        private readonly IFormatter eventFormatter;

        public const int CurrentVersion = 3;

        public UpgradeService(IDomainFacade domainFacade, IEventRebuilderStore eventStore, IFormatter eventFormatter)
        {
            Ensure.NotNull(domainFacade, "domainFacade");
            Ensure.NotNull(eventStore, "eventStore");
            Ensure.NotNull(eventFormatter, "eventFormatter");
            this.domainFacade = domainFacade;
            this.eventStore = eventStore;
            this.eventFormatter = eventFormatter;
        }

        public bool IsRequired()
        {
            return CurrentVersion > GetCurrentVersion();
        }

        public async Task UpgradeAsync(IUpgradeContext context)
        {
            int currentVersion = GetCurrentVersion();
            if (CurrentVersion <= currentVersion)
                return;

            context.TotalSteps(CurrentVersion - currentVersion);
            await Task.Delay(500);

            if (currentVersion < 1)
            {
                context.StartingStep(currentVersion - 0, "Creating default categories.");
                await UpgradeVersion1();
            }

            if (currentVersion < 2)
            {
                context.StartingStep(currentVersion - 1, "Rebuilding internal database.");
                await UpgradeVersion2();
            }

            if(currentVersion < 3)
            {
                context.StartingStep(currentVersion - 2, "Default currencies.");
                await UpgradeVersion3();
            }

            ApplicationDataContainer migrationContainer = GetMigrationContainer();
            migrationContainer.Values["Version"] = CurrentVersion;
        }

        private ApplicationDataContainer GetMigrationContainer()
        {
            ApplicationDataContainer root = ApplicationData.Current.LocalSettings;

            ApplicationDataContainer migrationContainer;
            if (!root.Containers.TryGetValue("Migration", out migrationContainer))
                migrationContainer = root.CreateContainer("Migration", ApplicationDataCreateDisposition.Always);

            return migrationContainer;
        }

        private int GetCurrentVersion()
        {
            ApplicationDataContainer migrationContainer = GetMigrationContainer();
            int currentVersion = (int?)migrationContainer.Values["Version"] ?? 0;
            return currentVersion;
        }

        private async Task UpgradeVersion1()
        {
            EventSourcingContext();
            await RecreateReadModelContext();

            await domainFacade.CreateCategoryAsync("Home", Colors.SandyBrown);
            await domainFacade.CreateCategoryAsync("Food", Colors.OrangeRed);
            await domainFacade.CreateCategoryAsync("Eating Out", Colors.DarkRed);
        }

        private Task UpgradeVersion2()
        {
            return RecreateReadModelContext();
        }

        private async Task UpgradeVersion3()
        {
            await domainFacade.CreateCurrencyAsync("CZK");
        }

        private void EventSourcingContext()
        {
            using (var eventSourcing = new EventSourcingContext())
            {
                eventSourcing.Database.EnsureDeleted();
                eventSourcing.Database.EnsureCreated();
                eventSourcing.Database.Migrate();
            }
        }

        private Task RecreateReadModelContext()
        {
            using (var readModels = new ReadModelContext())
            {
                readModels.Database.EnsureDeleted();
                readModels.Database.EnsureCreated();
            }

            // Should match with ReadModels.
            Rebuilder rebuilder = new Rebuilder(eventStore, eventFormatter);
            rebuilder.AddAll(new CategoryBuilder());
            rebuilder.AddAll(new OutcomeBuilder(domainFacade.PriceFactory));
{'fraction_non_alphanumeric': 0.076076993583868, 'fraction_numerical': 0.0034372135655362053, 'mean_word_length': 2.2583053378126166, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6633583', 'n_tokens_mistral': 2077, 'n_tokens_neox': 2026, 'n_words': 436}