/// <summary>
 /// Default constructor
 /// </summary>
 /// <param name="fileExtension">The file extension</param>
 /// <param name="magicHeader">The magic header</param>
 public FileFormatInfoAttribute(string fileExtension, uint magicHeader)
 {
     FileExtension = new FileExtension(fileExtension);
     MagicHeader   = magicHeader;
 }
        /// <summary>
        /// Converts the import file data from the input stream to the output stream
        /// </summary>
        /// <param name="fileBytes">The file bytes</param>
        /// <param name="inputStream">The input stream to import from</param>
        /// <param name="outputStream">The destination stream</param>
        /// <param name="format">The file format to use</param>
        public void ConvertImportData(byte[] fileBytes, Stream inputStream, Stream outputStream, FileExtension format)
        {
            // Load the bitmap
            using var bmp = new Bitmap(inputStream);

            // Load the current file
            OpenSpaceGFFile gf = GetFileContent(fileBytes);

            // IDEA: If bmp is not in supported format, then convert it?

            RawBitmapData rawBitmapData;

            // Get the bitmap lock
            using (var bmpLock = new BitmapLock(bmp))
            {
                // Get the raw bitmap data
                rawBitmapData = new RawBitmapData(bmp.Width, bmp.Height, bmpLock.Pixels, bmp.PixelFormat);

                // Check if the format should be updated for transparency
                if (RCPServices.Data.Archive_GF_UpdateTransparency != Archive_GF_TransparencyMode.PreserveFormat)
                {
                    // NOTE: Only 24 and 32 bpp bitmaps are supported
                    // Check if the imported file is transparent
                    var isTransparent = bmp.PixelFormat switch
                    {
                        PixelFormat.Format32bppArgb => (RCPServices.Data.Archive_GF_UpdateTransparency == Archive_GF_TransparencyMode.UpdateBasedOnPixelFormat ||
                                                        bmpLock.UtilizesAlpha()),
                        PixelFormat.Format24bppRgb => false,
                        _ => (bool?)null
                    };

                    // NOTE: Currently only supported for formats with 3 or 4 channels
                    // Check if the format should be updated for transparency
                    if (gf.Channels >= 3 && isTransparent != null)
                    {
                        // Update the format
                        gf.GFPixelFormat = isTransparent.Value ? OpenSpaceGFFormat.Format_32bpp_BGRA_8888 : OpenSpaceGFFormat.Format_24bpp_BGR_888;
                    }
                }
            }

            // Import the bitmap
            gf.ImportFromBitmap(Settings, rawBitmapData, RCPServices.Data.Archive_GF_GenerateMipmaps);

            // Serialize the data to get the bytes
            BinarySerializableHelpers.WriteToStream(gf, outputStream, Settings, RCPServices.App.GetBinarySerializerLogger());
        }

        #endregion
    }
        /// <summary>
        /// Exports the mipmaps from the file
        /// </summary>
        /// <param name="fileBytes">The file bytes</param>
        /// <param name="outputStreams">The function used to get the output streams for the mipmaps</param>
        /// <param name="format">The file extension to use</param>
        public void ExportMipmaps(byte[] fileBytes, Func <int, Stream> outputStreams, FileExtension format)
        {
            int index = 0;

            // Save each mipmap
            foreach (var bmp in GetBitmaps(fileBytes))
            {
                // Get the stream
                using var file = outputStreams(index);

                // Get the format
                var imgFormat = ImageHelpers.GetImageFormat(format);

                // Save the file
                bmp.Save(file, imgFormat);

                index++;
            }
        }
 /// <summary>
 /// Indicates if the file extension is the same as the TEX extension
 /// </summary>
 /// <param name="fileExtension">The file extension to check</param>
 /// <returns>True if it's the same</returns>
 protected bool IsTEXFormat(FileExtension fileExtension) => fileExtension == TEXFileExtension;
 /// <summary>
 /// Indicates if the file extension is the same as the file's native format
 /// </summary>
 /// <param name="fileExtension">The file extension to check</param>
 /// <returns>True if it's the same</returns>
 protected bool IsNativeFormat(FileExtension fileExtension) => fileExtension == FileExtension;
        /// <summary>
        /// Converts files using the specified serializer and convert action
        /// </summary>
        /// <typeparam name="T">The type of data to convert</typeparam>
        /// <param name="settings">The serializer settings</param>
        /// <param name="convertAction">The convert action, converting the data from the specified file path with the selected output format</param>
        /// <param name="fileFilter">The file filter when selecting files to convert</param>
        /// <param name="fileExtension">The file extension to export as</param>
        /// <param name="outputFormats">The available output formats</param>
        /// <param name="encoder">An optional data encoder to use</param>
        /// <returns>The task</returns>
        protected async Task ConvertToAsync <T>(IBinarySerializerSettings settings, Func <FileSystemPath, string, T> convertAction, string fileFilter, FileExtension fileExtension, string[] outputFormats = null, IDataEncoder encoder = null)
            where T : IBinarySerializable, new()
        {
            if (IsLoading)
            {
                return;
            }

            try
            {
                IsLoading = true;

                // Allow the user to select the files
                var fileResult = await Services.BrowseUI.BrowseFileAsync(new FileBrowserViewModel()
                {
                    Title           = Resources.Utilities_Converter_FileSelectionHeader,
                    ExtensionFilter = fileFilter,
                    MultiSelection  = true
                });

                if (fileResult.CanceledByUser)
                {
                    return;
                }

                // Allow the user to select the destination directory
                var destinationResult = await Services.BrowseUI.BrowseDirectoryAsync(new DirectoryBrowserViewModel()
                {
                    Title = Resources.Browse_DestinationHeader,
                });

                if (destinationResult.CanceledByUser)
                {
                    return;
                }

                try
                {
                    // The output format
                    string outputFormat = null;

                    // Get the output format if available
                    if (outputFormats?.Any() == true)
                    {
                        // Get the format
                        var formatResult = await RCPServices.UI.SelectFileExtensionAsync(new FileExtensionSelectionDialogViewModel(outputFormats, Resources.Utilities_Converter_FormatSelectionHeader));

                        if (formatResult.CanceledByUser)
                        {
                            return;
                        }

                        outputFormat = formatResult.SelectedFileFormat;
                    }

                    await Task.Run(() =>
                    {
                        // Convert every file
                        foreach (var file in fileResult.SelectedFiles)
                        {
                            // Get the destination file
                            var destinationFile = destinationResult.SelectedDirectory + file.Name;

                            // Set the file extension
                            destinationFile = destinationFile.ChangeFileExtension(fileExtension).GetNonExistingFileName();

                            // Convert the file
                            var data = convertAction(file, outputFormat);

                            if (encoder == null)
                            {
                                // Create the destination file
                                using var destinationFileStream = File.Open(destinationFile, FileMode.Create, FileAccess.Write);

                                // Save the converted data
                                BinarySerializableHelpers.WriteToStream(data, destinationFileStream, settings, RCPServices.App.GetBinarySerializerLogger());
                            }
                            else
                            {
                                // Create a memory stream
                                using var encodingStream = new MemoryStream();

                                // Serialize the converted data to the memory stream
                                BinarySerializableHelpers.WriteToStream(data, encodingStream, settings, RCPServices.App.GetBinarySerializerLogger());

                                // Create the destination file
                                using var destinationFileStream = File.Open(destinationFile, FileMode.Create, FileAccess.Write);

                                encodingStream.Position = 0;

                                // Encode the data to the file
                                encoder.Encode(encodingStream, destinationFileStream);
                            }
                        }
                    });

                    await Services.MessageUI.DisplaySuccessfulActionMessageAsync(Resources.Utilities_Converter_Success);
                }
                catch (Exception ex)
                {
                    ex.HandleError("Converting files");

                    await Services.MessageUI.DisplayExceptionMessageAsync(ex, Resources.Utilities_Converter_Error);
                }
            }
            finally
            {
                IsLoading = false;
            }
        }