/// <summary>
        /// Analyzes the sprite sequence for issues
        /// </summary>
        /// <param name="errs">The errors found within the animation clip</param>
        /// <param name="spriteSequence">The sprite sequence to analyze</param>
        /// <returns>The errors, if any</returns>
        public static void Analyze(StringBuilder errs, SpriteSequence spriteSequence)
        {
            // Check that the name matches
            var fileBaseName = Path.GetFileName(spriteSequence.fmt);

            fileBaseName = fileBaseName.Substring(0, fileBaseName.LastIndexOf('_'));
            if (spriteSequence.name != fileBaseName)
            {
                errs.AppendLine($"{spriteSequence.name}: sprite images have a different base name ({fileBaseName}) from folder.");
            }

            // Check the number of frames
            if (spriteSequence.Count < 1)
            {
                errs.AppendLine($"{spriteSequence.name}: sprite sequence doesn't contain any names.");
                return;
            }

#if false
            // Check the duration
            if (spriteSequence.length_ms < 5)
            {
                errs.AppendLine($"{spriteSequence.name}: sprite sequence duration is far too short.");
                return(errs);
            }
            // Check the framerate
            if (spriteSequence.FramesPerSecond > 15)
            {
                errs.AppendLine($"{spriteSequence.name}: sprite sequence frame rate is too high.");
                return(errs);
            }
#endif
        }
        /// <summary>
        /// Analyzes the sprite sequence for issues
        /// </summary>
        /// <param name="errs">The errors found within the animation clip</param>
        /// <param name="spriteSequence">The sprite sequence to analyze</param>
        /// <param name="width">The width of the sprite display area</param>
        /// <param name="height">The height of the sprite display area</param>
        /// <returns>The errors, if any</returns>
        static void Analyze(StringBuilder errs, SpriteSequence spriteSequence, uint width, uint height)
        {
            // Scan over each of the images and check the size
            int idx = 0;

            foreach (var img in spriteSequence.Bitmaps)
            {
                // Check the image
                if (img.Width != width || img.Height != height)
                {
                    errs.AppendLine($"{spriteSequence.name}[{idx}]: image is wrong size.  Expected {width}x{height} got {img.Width}x{img.Height}");
                }

                // And dispose of the resources
                img.Dispose();
                idx++;
            }
        }
        /// <summary>
        /// This is used to provide a sprite sequence for the sequence name.
        /// </summary>
        /// <param name="sequenceName">The name of the sprite sequence</param>
        /// <returns>An enumeration of the sprite paths relative to the resources base</returns>
        public SpriteSequence SpriteSequence(string sequenceName)
        {
            // Build the sprite sequence paths cache
            BuildSpriteSequencePaths();

            // Construct a path looking for the animation group
            if (!spriteSequencePathCache.TryGetValue(sequenceName.ToUpper(), out var sequencePath))
            {
                return(null);
            }
            var name = sequenceName;

            // The file inside of the folder don't always have the exact same name.
            // Figure that out from first name
            var d = Directory.EnumerateFiles(Path.Combine(cozmoResourcesPath, sequencePath));
            var e = d.GetEnumerator();

            e.MoveNext();
            var template = e.Current;

            sequenceName = Path.GetFileName(template.Substring(0, template.LastIndexOf('_')));

            // The path and file name prefix
            sequencePath = Path.Combine(sequencePath, sequenceName + "_");

            // probe to see the number of digits to use with the template
            // There may be a better way, but this works
            var fmt = "{0:D5}.png";

            if (File.Exists(Path.Combine(cozmoResourcesPath, sequencePath + "00.png")))
            {
                fmt = "{0:D2}.png";
            }
            else if (File.Exists(Path.Combine(cozmoResourcesPath, sequencePath + "000.png")))
            {
                fmt = "{0:D3}.png";
            }
            else if (File.Exists(Path.Combine(cozmoResourcesPath, sequencePath + "0000.png")))
            {
                fmt = "{0:D4}.png";
            }

            // Creates the wrapper around the sprites
            var ret = new SpriteSequence(name, cozmoResourcesPath, sequencePath + fmt);
            // Since it is faster here, count the number of items
            var dir = new Dictionary <string, string>();

            foreach (var x in d)
            {
                dir[Path.GetFileName(x)] = x;
            }
            for (int I = dir.Count; I >= 0; I--)
            {
                if (dir.ContainsKey(sequenceName + "_" + String.Format(fmt, I)))
                {
                    ret.Count = I + 1;
                    break;
                }
            }


            // Creates the wrapper around the sprites
            return(ret);
        }