using System;
using System.Linq;
using SabreTools.Metadata.DatFiles.Formats;
using SabreTools.Metadata.DatItems.Formats;
using Xunit;

namespace SabreTools.Metadata.DatFiles.Test
{
    /// <summary>
    /// Contains tests for all specific DatFile formats
    /// </summary>
    public class FormatsTests
    {
        #region Testing Constants

        /// <summary>
        /// All defined item types
        /// </summary>
        private static readonly Data.Models.Metadata.ItemType[] AllTypes = Enum.GetValues<Data.Models.Metadata.ItemType>();

        #endregion

        #region ArchiveDotOrg

        [Fact]
        public void ArchiveDotOrg_SupportedTypes()
        {
            var datFile = new ArchiveDotOrg(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        #endregion

        #region AttractMode

        [Fact]
        public void AttractMode_SupportedTypes()
        {
            var datFile = new AttractMode(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void AttractMode_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new AttractMode(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
            ]));
        }

        #endregion

        #region ClrMamePro

        [Fact]
        public void ClrMamePro_SupportedTypes()
        {
            var datFile = new ClrMamePro(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Archive,
                Data.Models.Metadata.ItemType.BiosSet,
                Data.Models.Metadata.ItemType.Chip,
                Data.Models.Metadata.ItemType.DipSwitch,
                Data.Models.Metadata.ItemType.Disk,
                Data.Models.Metadata.ItemType.Display,
                Data.Models.Metadata.ItemType.Driver,
                Data.Models.Metadata.ItemType.Input,
                Data.Models.Metadata.ItemType.Media,
                Data.Models.Metadata.ItemType.Release,
                Data.Models.Metadata.ItemType.Rom,
                Data.Models.Metadata.ItemType.Sample,
                Data.Models.Metadata.ItemType.Sound,
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_Release()
        {
            var datItem = new Release();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Release.Name),
                nameof(Data.Models.Metadata.Release.Region),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_BiosSet()
        {
            var datItem = new BiosSet();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.BiosSet.Name),
                nameof(Data.Models.Metadata.BiosSet.Description),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.Size),
                nameof(Data.Models.Metadata.Rom.SHA1),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_Disk()
        {
            var datItem = new Disk();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Disk.Name),
                nameof(Data.Models.Metadata.Disk.SHA1),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_Sample()
        {
            var datItem = new Sample();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Sample.Name),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_Archive()
        {
            var datItem = new Archive();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Archive.Name),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_Chip()
        {
            var datItem = new Chip();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Chip.ChipType),
                nameof(Data.Models.Metadata.Chip.Name),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_Display()
        {
            var datItem = new Display();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Display.DisplayType),
                nameof(Data.Models.Metadata.Display.Rotate),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_Sound()
        {
            var datItem = new Sound();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Sound.Channels),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_Input()
        {
            var datItem = new Input();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Input.Players),
                nameof(Data.Models.Metadata.Input.Control),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_DipSwitch()
        {
            var datItem = new DipSwitch();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.DipSwitch.Name),
            ]));
        }

        [Fact]
        public void ClrMamePro_GetMissingRequiredFields_Driver()
        {
            var datItem = new Driver();
            var datFile = new ClrMamePro(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Driver.Status),
                nameof(Data.Models.Metadata.Driver.Emulation),
            ]));
        }

        #endregion

        #region DosCenter

        [Fact]
        public void DosCenter_SupportedTypes()
        {
            var datFile = new DosCenter(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void DosCenter_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new DosCenter(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.Size),
                nameof(Data.Models.Metadata.Rom.CRC32),
            ]));
        }

        #endregion

        #region EverdriveSMDB

        [Fact]
        public void EverdriveSMDB_SupportedTypes()
        {
            var datFile = new EverdriveSMDB(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void EverdriveSMDB_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new EverdriveSMDB(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.SHA256),
                nameof(Data.Models.Metadata.Rom.SHA1),
                nameof(Data.Models.Metadata.Rom.MD5),
                nameof(Data.Models.Metadata.Rom.CRC32),
            ]));
        }

        #endregion

        #region Hashfile

        [Fact]
        public void SfvFile_SupportedTypes()
        {
            var datFile = new SfvFile(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void SfvFile_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new SfvFile(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.CRC32),
            ]));
        }

        [Fact]
        public void Md2File_SupportedTypes()
        {
            var datFile = new Md2File(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void Md2File_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Md2File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.MD2),
            ]));
        }

        [Fact]
        public void Md4File_SupportedTypes()
        {
            var datFile = new Md4File(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void Md4File_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Md4File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.MD4),
            ]));
        }

        [Fact]
        public void Md5File_SupportedTypes()
        {
            var datFile = new Md5File(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Disk,
                Data.Models.Metadata.ItemType.Media,
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void Md5File_GetMissingRequiredFields_Disk()
        {
            var datItem = new Disk();
            var datFile = new Md5File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Disk.Name),
                nameof(Data.Models.Metadata.Disk.MD5),
            ]));
        }

        [Fact]
        public void Md5File_GetMissingRequiredFields_Media()
        {
            var datItem = new Media();
            var datFile = new Md5File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Media.Name),
                nameof(Data.Models.Metadata.Media.MD5),
            ]));
        }

        [Fact]
        public void Md5File_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Md5File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.MD5),
            ]));
        }

        [Fact]
        public void RipeMD128File_SupportedTypes()
        {
            var datFile = new RipeMD128File(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void RipeMD128File_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new RipeMD128File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.RIPEMD128),
            ]));
        }

        [Fact]
        public void RipeMD160File_SupportedTypes()
        {
            var datFile = new RipeMD160File(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void RipeMD160File_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new RipeMD160File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.RIPEMD160),
            ]));
        }

        [Fact]
        public void Sha1File_SupportedTypes()
        {
            var datFile = new Sha1File(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Disk,
                Data.Models.Metadata.ItemType.Media,
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void Sha1File_GetMissingRequiredFields_Disk()
        {
            var datItem = new Disk();
            var datFile = new Sha1File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Disk.Name),
                nameof(Data.Models.Metadata.Disk.SHA1),
            ]));
        }

        [Fact]
        public void Sha1File_GetMissingRequiredFields_Media()
        {
            var datItem = new Media();
            var datFile = new Sha1File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Media.Name),
                nameof(Data.Models.Metadata.Media.SHA1),
            ]));
        }

        [Fact]
        public void Sha1File_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Sha1File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.SHA1),
            ]));
        }

        [Fact]
        public void Sha256File_SupportedTypes()
        {
            var datFile = new Sha256File(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Media,
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void Sha256File_GetMissingRequiredFields_Media()
        {
            var datItem = new Media();
            var datFile = new Sha256File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Media.Name),
                nameof(Data.Models.Metadata.Media.SHA256),
            ]));
        }

        [Fact]
        public void Sha256File_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Sha256File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.SHA256),
            ]));
        }

        [Fact]
        public void Sha384File_SupportedTypes()
        {
            var datFile = new Sha384File(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void Sha384File_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Sha384File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.SHA384),
            ]));
        }

        [Fact]
        public void Sha512File_SupportedTypes()
        {
            var datFile = new Sha512File(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void Sha512File_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Sha512File(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.SHA512),
            ]));
        }

        [Fact]
        public void SpamSumFile_SupportedTypes()
        {
            var datFile = new SpamSumFile(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Media,
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void SpamSumFile_GetMissingRequiredFields_Media()
        {
            var datItem = new Media();
            var datFile = new SpamSumFile(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Media.Name),
                nameof(Data.Models.Metadata.Media.SpamSum),
            ]));
        }

        [Fact]
        public void SpamSumFile_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new SpamSumFile(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.SpamSum),
            ]));
        }

        #endregion

        #region Listrom

        [Fact]
        public void Listrom_SupportedTypes()
        {
            var datFile = new Listrom(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Disk,
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void Listrom_GetMissingRequiredFields_Disk()
        {
            var datItem = new Disk();
            var datFile = new Listrom(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Disk.Name),
                nameof(Data.Models.Metadata.Disk.SHA1),
            ]));
        }

        [Fact]
        public void Listrom_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Listrom(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.Size),
                nameof(Data.Models.Metadata.Rom.CRC32),
                nameof(Data.Models.Metadata.Rom.SHA1),
            ]));
        }

        #endregion

        #region Listxml

        [Fact]
        public void Listxml_SupportedTypes()
        {
            var datFile = new Listxml(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Adjuster,
                Data.Models.Metadata.ItemType.BiosSet,
                Data.Models.Metadata.ItemType.Chip,
                Data.Models.Metadata.ItemType.Configuration,
                Data.Models.Metadata.ItemType.Device,
                Data.Models.Metadata.ItemType.DeviceRef,
                Data.Models.Metadata.ItemType.DipSwitch,
                Data.Models.Metadata.ItemType.Disk,
                Data.Models.Metadata.ItemType.Display,
                Data.Models.Metadata.ItemType.Driver,
                Data.Models.Metadata.ItemType.Feature,
                Data.Models.Metadata.ItemType.Input,
                Data.Models.Metadata.ItemType.Port,
                Data.Models.Metadata.ItemType.RamOption,
                Data.Models.Metadata.ItemType.Rom,
                Data.Models.Metadata.ItemType.Sample,
                Data.Models.Metadata.ItemType.Slot,
                Data.Models.Metadata.ItemType.SoftwareList,
                Data.Models.Metadata.ItemType.Sound,
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_BiosSet()
        {
            var datItem = new BiosSet();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.BiosSet.Name),
                nameof(Data.Models.Metadata.BiosSet.Description),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.Size),
                nameof(Data.Models.Metadata.Rom.SHA1),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Disk()
        {
            var datItem = new Disk();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Disk.Name),
                nameof(Data.Models.Metadata.Disk.SHA1),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_DeviceRef()
        {
            var datItem = new DeviceRef();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.DeviceRef.Name),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Sample()
        {
            var datItem = new Sample();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Sample.Name),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Chip()
        {
            var datItem = new Chip();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Chip.Name),
                nameof(Data.Models.Metadata.Chip.ChipType),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Display()
        {
            var datItem = new Display();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Display.DisplayType),
                nameof(Data.Models.Metadata.Display.Refresh),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Sound()
        {
            var datItem = new Sound();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Sound.Channels),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Input()
        {
            var datItem = new Input();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Input.Players),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_DipSwitch()
        {
            var datItem = new DipSwitch();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.DipSwitch.Name),
                nameof(Data.Models.Metadata.DipSwitch.Tag),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Configuration()
        {
            var datItem = new Configuration();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Configuration.Name),
                nameof(Data.Models.Metadata.Configuration.Tag),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Port()
        {
            var datItem = new Port();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Port.Tag),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Adjuster()
        {
            var datItem = new Adjuster();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Adjuster.Name),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Driver()
        {
            var datItem = new Driver();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Driver.Status),
                nameof(Data.Models.Metadata.Driver.Emulation),
                nameof(Data.Models.Metadata.Driver.Cocktail),
                nameof(Data.Models.Metadata.Driver.SaveState),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Feature()
        {
            var datItem = new Feature();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Feature.FeatureType),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Device()
        {
            var datItem = new Device();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Device.DeviceType),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_Slot()
        {
            var datItem = new Slot();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Slot.Name),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_SoftwareList()
        {
            var datItem = new DatItems.Formats.SoftwareList();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.SoftwareList.Tag),
                nameof(Data.Models.Metadata.SoftwareList.Name),
                nameof(Data.Models.Metadata.SoftwareList.Status),
            ]));
        }

        [Fact]
        public void Listxml_GetMissingRequiredFields_RamOption()
        {
            var datItem = new RamOption();
            var datFile = new Listxml(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.RamOption.Name),
            ]));
        }

        #endregion

        #region Logiqx

        [Fact]
        public void Logiqx_SupportedTypes()
        {
            var datFile = new Logiqx(null, false);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Archive,
                Data.Models.Metadata.ItemType.BiosSet,
                Data.Models.Metadata.ItemType.DeviceRef,
                Data.Models.Metadata.ItemType.Disk,
                Data.Models.Metadata.ItemType.Driver,
                Data.Models.Metadata.ItemType.Media,
                Data.Models.Metadata.ItemType.Release,
                Data.Models.Metadata.ItemType.Rom,
                Data.Models.Metadata.ItemType.Sample,
                Data.Models.Metadata.ItemType.SoftwareList,
            ]));
        }

        [Fact]
        public void Logiqx_GetMissingRequiredFields_Release()
        {
            var datItem = new Release();
            var datFile = new Logiqx(null, false);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Release.Name),
                nameof(Data.Models.Metadata.Release.Region),
            ]));
        }

        [Fact]
        public void Logiqx_GetMissingRequiredFields_BiosSet()
        {
            var datItem = new BiosSet();
            var datFile = new Logiqx(null, false);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.BiosSet.Name),
                nameof(Data.Models.Metadata.BiosSet.Description),
            ]));
        }

        [Fact]
        public void Logiqx_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Logiqx(null, false);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.Size),
                nameof(Data.Models.Metadata.Rom.SHA1),
            ]));
        }

        [Fact]
        public void Logiqx_GetMissingRequiredFields_Disk()
        {
            var datItem = new Disk();
            var datFile = new Logiqx(null, false);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Disk.Name),
                nameof(Data.Models.Metadata.Disk.SHA1),
            ]));
        }

        [Fact]
        public void Logiqx_GetMissingRequiredFields_Media()
        {
            var datItem = new Media();
            var datFile = new Logiqx(null, false);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Media.Name),
                nameof(Data.Models.Metadata.Media.SHA1),
            ]));
        }

        [Fact]
        public void Logiqx_GetMissingRequiredFields_DeviceRef()
        {
            var datItem = new DeviceRef();
            var datFile = new Logiqx(null, false);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.DeviceRef.Name),
            ]));
        }

        [Fact]
        public void Logiqx_GetMissingRequiredFields_Sample()
        {
            var datItem = new Sample();
            var datFile = new Logiqx(null, false);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Sample.Name),
            ]));
        }

        [Fact]
        public void Logiqx_GetMissingRequiredFields_Archive()
        {
            var datItem = new Archive();
            var datFile = new Logiqx(null, false);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Archive.Name),
            ]));
        }

        [Fact]
        public void Logiqx_GetMissingRequiredFields_Driver()
        {
            var datItem = new Driver();
            var datFile = new Logiqx(null, false);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Driver.Status),
                nameof(Data.Models.Metadata.Driver.Emulation),
                nameof(Data.Models.Metadata.Driver.Cocktail),
                nameof(Data.Models.Metadata.Driver.SaveState),
            ]));
        }

        [Fact]
        public void Logiqx_GetMissingRequiredFields_SoftwareList()
        {
            var datItem = new DatItems.Formats.SoftwareList();
            var datFile = new Logiqx(null, false);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.SoftwareList.Tag),
                nameof(Data.Models.Metadata.SoftwareList.Name),
                nameof(Data.Models.Metadata.SoftwareList.Status),
            ]));
        }

        #endregion

        #region Missfile

        [Fact]
        public void Missfile_SupportedTypes()
        {
            var datFile = new Missfile(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual(AllTypes));
        }

        [Fact]
        public void Missfile_ParseFile_Throws()
        {
            var datFile = new Missfile(null);
            Assert.Throws<NotImplementedException>(() => datFile.ParseFile("path", 0, true));
        }

        #endregion

        #region OfflineList

        [Fact]
        public void OfflineList_SupportedTypes()
        {
            var datFile = new OfflineList(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void OfflineList_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new OfflineList(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Size),
                nameof(Data.Models.Metadata.Rom.CRC32),
            ]));
        }

        #endregion

        #region OpenMSX

        [Fact]
        public void OpenMSX_SupportedTypes()
        {
            var datFile = new OpenMSX(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void OpenMSX_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new OpenMSX(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.SHA1),
            ]));
        }

        #endregion

        #region RomCenter

        [Fact]
        public void RomCenter_SupportedTypes()
        {
            var datFile = new RomCenter(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void RomCenter_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new RomCenter(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.CRC32),
                nameof(Data.Models.Metadata.Rom.Size),
            ]));
        }

        #endregion

        #region SabreJSON

        [Fact]
        public void SabreJSON_SupportedTypes()
        {
            var datFile = new SabreJSON(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual(AllTypes));
        }

        #endregion

        #region SabreXML

        [Fact]
        public void SabreXML_SupportedTypes()
        {
            var datFile = new SabreXML(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual(AllTypes));
        }

        #endregion

        #region SeparatedValue

        [Fact]
        public void CommaSeparatedValue_SupportedTypes()
        {
            var datFile = new CommaSeparatedValue(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Disk,
                Data.Models.Metadata.ItemType.Media,
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void CommaSeparatedValue_GetMissingRequiredFields_Disk()
        {
            var datItem = new Disk();
            var datFile = new CommaSeparatedValue(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Disk.Name),
                nameof(Data.Models.Metadata.Disk.SHA1),
            ]));
        }

        [Fact]
        public void CommaSeparatedValue_GetMissingRequiredFields_Media()
        {
            var datItem = new Media();
            var datFile = new CommaSeparatedValue(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Media.Name),
                nameof(Data.Models.Metadata.Media.SHA1),
            ]));
        }

        [Fact]
        public void CommaSeparatedValue_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new CommaSeparatedValue(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.Size),
                nameof(Data.Models.Metadata.Rom.SHA1),
            ]));
        }

        [Fact]
        public void SemicolonSeparatedValue_SupportedTypes()
        {
            var datFile = new SemicolonSeparatedValue(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Disk,
                Data.Models.Metadata.ItemType.Media,
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void SemicolonSeparatedValue_GetMissingRequiredFields_Disk()
        {
            var datItem = new Disk();
            var datFile = new SemicolonSeparatedValue(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Disk.Name),
                nameof(Data.Models.Metadata.Disk.SHA1),
            ]));
        }

        [Fact]
        public void SemicolonSeparatedValue_GetMissingRequiredFields_Media()
        {
            var datItem = new Media();
            var datFile = new SemicolonSeparatedValue(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Media.Name),
                nameof(Data.Models.Metadata.Media.SHA1),
            ]));
        }

        [Fact]
        public void SemicolonSeparatedValue_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new SemicolonSeparatedValue(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.Size),
                nameof(Data.Models.Metadata.Rom.SHA1),
            ]));
        }

        [Fact]
        public void TabSeparatedValue_SupportedTypes()
        {
            var datFile = new TabSeparatedValue(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.Disk,
                Data.Models.Metadata.ItemType.Media,
                Data.Models.Metadata.ItemType.Rom,
            ]));
        }

        [Fact]
        public void TabSeparatedValue_GetMissingRequiredFields_Disk()
        {
            var datItem = new Disk();
            var datFile = new TabSeparatedValue(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Disk.Name),
                nameof(Data.Models.Metadata.Disk.SHA1),
            ]));
        }

        [Fact]
        public void TabSeparatedValue_GetMissingRequiredFields_Media()
        {
            var datItem = new Media();
            var datFile = new TabSeparatedValue(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Media.Name),
                nameof(Data.Models.Metadata.Media.SHA1),
            ]));
        }

        [Fact]
        public void TabSeparatedValue_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new TabSeparatedValue(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Rom.Name),
                nameof(Data.Models.Metadata.Rom.Size),
                nameof(Data.Models.Metadata.Rom.SHA1),
            ]));
        }

        #endregion

        #region SoftwareList

        [Fact]
        public void SoftwareList_SupportedTypes()
        {
            var datFile = new Formats.SoftwareList(null);
            var actual = datFile.SupportedTypes;
            Assert.True(actual.SequenceEqual([
                Data.Models.Metadata.ItemType.DipSwitch,
                Data.Models.Metadata.ItemType.Disk,
                Data.Models.Metadata.ItemType.Info,
                Data.Models.Metadata.ItemType.PartFeature,
                Data.Models.Metadata.ItemType.Rom,
                Data.Models.Metadata.ItemType.SharedFeat,
            ]));
        }

        [Fact]
        public void SoftwareList_GetMissingRequiredFields_DipSwitch()
        {
            var datItem = new DipSwitch();
            var datFile = new Formats.SoftwareList(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Part.Name),
                nameof(Data.Models.Metadata.Part.Interface),
                nameof(Data.Models.Metadata.DipSwitch.Name),
                nameof(Data.Models.Metadata.DipSwitch.Tag),
                nameof(Data.Models.Metadata.DipSwitch.Mask),
            ]));
        }

        [Fact]
        public void SoftwareList_GetMissingRequiredFields_Disk()
        {
            var datItem = new Disk();
            var datFile = new Formats.SoftwareList(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Part.Name),
                nameof(Data.Models.Metadata.Part.Interface),
                nameof(Data.Models.Metadata.DiskArea.Name),
                nameof(Data.Models.Metadata.Disk.Name),
            ]));
        }

        [Fact]
        public void SoftwareList_GetMissingRequiredFields_Info()
        {
            var datItem = new Info();
            var datFile = new Formats.SoftwareList(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Info.Name),
            ]));
        }

        [Fact]
        public void SoftwareList_GetMissingRequiredFields_Rom()
        {
            var datItem = new Rom();
            var datFile = new Formats.SoftwareList(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.Part.Name),
                nameof(Data.Models.Metadata.Part.Interface),
                nameof(Data.Models.Metadata.DataArea.Name),
                nameof(Data.Models.Metadata.DataArea.Size),
            ]));
        }

        [Fact]
        public void SoftwareList_GetMissingRequiredFields_SharedFeat()
        {
            var datItem = new SharedFeat();
            var datFile = new Formats.SoftwareList(null);

            var actual = datFile.GetMissingRequiredFields(datItem);

            Assert.NotNull(actual);
            Assert.True(actual.SequenceEqual([
                nameof(Data.Models.Metadata.SharedFeat.Name),
            ]));
        }

        #endregion
    }
}
