// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.IO;
using osu.Game.Rulesets;
using osu.Game.Tests.Resources;

namespace osu.Game.Tests.Database
{
    [TestFixture]
    public class LegacyBeatmapImporterTest : RealmTest
    {
        private readonly TestLegacyBeatmapImporter importer = new TestLegacyBeatmapImporter();

        [Test]
        public void TestSongsSubdirectories()
        {
            using (var storage = new TemporaryNativeStorage("stable-songs-folder"))
            {
                var songsStorage = storage.GetStorageForDirectory(StableStorage.STABLE_DEFAULT_SONGS_PATH);

                // normal beatmap folder
                var beatmap1 = songsStorage.GetStorageForDirectory("beatmap1");
                createFile(beatmap1, "beatmap.osu");

                // songs subdirectory
                var subdirectory = songsStorage.GetStorageForDirectory("subdirectory");
                createFile(subdirectory, Path.Combine("beatmap2", "beatmap.osu"));
                createFile(subdirectory, Path.Combine("beatmap3", "beatmap.osu"));
                createFile(subdirectory, Path.Combine("sub-subdirectory", "beatmap4", "beatmap.osu"));

                // songs subdirectory with system file
                var subdirectory2 = songsStorage.GetStorageForDirectory("subdirectory2");
                createFile(subdirectory2, ".DS_Store");
                createFile(subdirectory2, Path.Combine("beatmap5", "beatmap.osu"));
                createFile(subdirectory2, Path.Combine("beatmap6", "beatmap.osu"));

                // songs subdirectory with random file
                var subdirectory3 = songsStorage.GetStorageForDirectory("subdirectory3");
                createFile(subdirectory3, "silly readme.txt");
                createFile(subdirectory3, Path.Combine("beatmap7", "beatmap.osu"));

                // empty songs subdirectory
                songsStorage.GetStorageForDirectory("subdirectory3");

                string[] paths = importer.GetStableImportPaths(songsStorage).ToArray();
                Assert.That(paths.Length, Is.EqualTo(7));
                Assert.That(paths.Contains(songsStorage.GetFullPath("beatmap1")));
                Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory", "beatmap2"))));
                Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory", "beatmap3"))));
                Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory", "sub-subdirectory", "beatmap4"))));
                Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory2", "beatmap5"))));
                Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory2", "beatmap6"))));
                Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory3", "beatmap7"))));
            }

            static void createFile(Storage storage, string path)
            {
                using (var stream = storage.CreateFileSafely(path))
                    stream.WriteByte(0);
            }
        }

        [Test]
        public void TestStableDateAddedApplied()
        {
            RunTestWithRealmAsync(async (realm, storage) =>
            {
                using (HeadlessGameHost host = new CleanRunHeadlessGameHost())
                using (var tmpStorage = new TemporaryNativeStorage("stable-songs-folder"))
                using (new RealmRulesetStore(realm, storage))
                {
                    var stableStorage = new StableStorage(tmpStorage.GetFullPath(""), host);
                    var songsStorage = stableStorage.GetStorageForDirectory(StableStorage.STABLE_DEFAULT_SONGS_PATH);

                    ZipFile.ExtractToDirectory(TestResources.GetQuickTestBeatmapForImport(), songsStorage.GetFullPath("renatus"));

                    string[] beatmaps = Directory.GetFiles(songsStorage.GetFullPath("renatus"), "*.osu", SearchOption.TopDirectoryOnly);

                    File.SetLastWriteTimeUtc(beatmaps[beatmaps.Length / 2], new DateTime(2000, 1, 1, 12, 0, 0));

                    await new LegacyBeatmapImporter(new BeatmapImporter(storage, realm)).ImportFromStableAsync(stableStorage);

                    var importedSet = realm.Realm.All<BeatmapSetInfo>().Single();

                    Assert.NotNull(importedSet);
                    Assert.AreEqual(new DateTimeOffset(new DateTime(2000, 1, 1, 12, 0, 0, DateTimeKind.Utc)), importedSet.DateAdded);
                }
            });
        }

        private class TestLegacyBeatmapImporter : LegacyBeatmapImporter
        {
            public TestLegacyBeatmapImporter()
                : base(null!)
            {
            }

            public new IEnumerable<string> GetStableImportPaths(Storage storage) => base.GetStableImportPaths(storage);
        }
    }
}