protected void WriteComponents(ECSFile ecsFile)
        {
            var genericCount = ecsFile.components?.Count ?? 0;
            var generics     = genericCount.Range().Select(i => $"T{i}").ToArray();
            var spanGenerics = genericCount.Range().Select(i => $"Span<T{i}> t{i}");

            var where = genericCount.Range().Select(i => $"where T{i}: unmanaged").ToArray();
            var componentType     = genericCount.Range().Select(i => $"ComponentType<T{i}>.Type").ToArray();
            var componentIndicies = genericCount.Range().Select(i => $"var c{i} = array.Specification.GetComponentIndex(componentTypes[{i}]);").ToArray();
            var componentArrays   = genericCount.Range().Select(i => $"var t{i} = chunk.GetComponentData<T{i}>(c{i}, componentTypes[{i}]);").ToArray();
            var viewArgs          = genericCount.Range().Select(i => $"t{i}");

            //WriteLine($"public delegate void ForEachChunk<{generics.Join()}>(int length, ReadOnlySpan<EntityRef> entities, {spanGenerics.Join()}){where.Join(" ")};");
            //WriteLine($"public unsafe static void ForChunk<{generics.Join()}>(this EntityManager em, ForEachChunk<{generics.Join()}> view) ");
            //WriteLine($"  {where.Join(" ")}");
            //WriteLine($"{{");
            //WriteLine($"Span<ComponentType> componentTypes = stackalloc ComponentType[] {{ {componentType.Join()} }};");
            WriteLine($"Span<ComponentType> componentTypes = stackalloc ComponentType[] {{");
            _indent++;
            for (var i = 0; i < ecsFile.components?.Count; i++)
            {
                var c = ecsFile.components[i];

                WriteLine($"ComponentType<{c.type}>.Type" + (i < ecsFile.components.Count - 1 ? "," : ""));
            }
            _indent--;
            WriteLine("}};");
            WriteLine($"var entityArrays = em.EntityArrays;");
            WriteLine($"for (var i = 0; i < entityArrays.Count; i++) {{");
            _indent++;
            WriteLine($"var array = entityArrays[i];");
            WriteLine($"if (array.Specification.HasAll(componentTypes)) {{");
            _indent++;

            WriteLine(componentIndicies);
            WriteLine($"for (var k = 0; k < array.AllChunks.Count; k++) {{");
            _indent++;
            WriteLine($"var chunk = array.AllChunks[k];");

            WriteLine($"system.entities = chunk.Entities;");
            for (var i = 0; i < ecsFile.components?.Count; i++)
            {
                var c = ecsFile.components[i];

                WriteLine($"system.{c.name} = chunk.GetComponentData<{c.type}>(c{i}, componentTypes[{i}]);");
            }
            WriteLine($"system.Execute(chunk.Count);");
            for (var i = 0; i < ecsFile.buffers?.Count; i++)
            {
                var b = ecsFile.buffers[i];
                if (b.flush)
                {
                    WriteLine($"system.{b.name}.Execute(em);");
                }
            }
            _indent--;
            WriteLine($"}}");
            _indent--;
            WriteLine($"}}");
            _indent--;
            WriteLine($"}}");
            //WriteLine($"}}");
        }
        protected int ProcessFile(Manifest m, ProjectGroup group, string file)
        {
            var name = Path.GetFileNameWithoutExtension(file);

            while (name.Contains('.'))
            {
                name = Path.GetFileNameWithoutExtension(name);
            }

            var dir     = Path.GetDirectoryName(file);
            var dstFile = Path.Combine(dir, name + ".ecs.cs");

            var srcInfo = new FileInfo(file);
            var dstInfo = new FileInfo(dstFile);

            if (!Force && srcInfo.LastWriteTimeUtc == dstInfo.LastWriteTimeUtc)
            {
                Console.WriteLine($"Skipping   [{file}], not modified.");
                return(0);
            }

            Console.WriteLine($"Generating [{file}].");

            output = Console.Out;

            var ns = group.name;

            if (!string.IsNullOrEmpty(m.@namespace))
            {
                ns = m.@namespace + "." + group.name;
            }

            ECSFile ecsFile = null;

            using (var sr = File.OpenRead(file))
                ecsFile = Utf8Json.JsonSerializer.Deserialize <ECSFile>(sr);

            if (string.IsNullOrEmpty(ecsFile.name))
            {
                ecsFile.name = name;
            }

            if (!console)
            {
                output = File.CreateText(dstFile);
            }

            try
            {
                WriteLine($"namespace {ns}{{");
                _indent++;
                WriteLine($"using System;");
                WriteLine($"using Atma.Common;");
                WriteLine($"using Atma.Memory;");
                WriteLine($"using Atma.Entities;");

                WriteLine($"public ref partial struct {ecsFile.name}{{");
                _indent++;
                for (var i = 0; i < ecsFile.variables?.Count; i++)
                {
                    var v = ecsFile.variables[i];
                    WriteLine($"public {v.type} {v.name};");
                }

                for (var i = 0; i < ecsFile.buffers?.Count; i++)
                {
                    var b = ecsFile.buffers[i];
                    WriteLine($"public EntityCommandBuffer {b.name};");
                }


                WriteLine("public ReadOnlySpan<EntityRef> entities;");
                for (var i = 0; i < ecsFile.components?.Count; i++)
                {
                    var c    = ecsFile.components[i];
                    var type = $"ReadOnlySpan";
                    if (c.write)
                    {
                        type = $"Span";
                    }

                    WriteLine($"public {type}<{c.type}> {c.name};");
                }

                WriteLine($"public static void Process(SystemManager sm, EntityManager em) {{");
                _indent++;
                WriteLine($"var system = new {ecsFile.name}();");
                for (var i = 0; i < ecsFile.variables?.Count; i++)
                {
                    var v = ecsFile.variables[i];
                    WriteLine($"system.{v.name} = sm.Variable<{v.name}>(\"{v.name}\");");
                }

                for (var i = 0; i < ecsFile.buffers?.Count; i++)
                {
                    var b = ecsFile.buffers[i];
                    if (b.size > 0)
                    {
                        WriteLine($"system.{b.name} = sm.CreateCommandBuffer({b.size});");
                    }
                    else
                    {
                        WriteLine($"system.{b.name} = sm.CreateCommandBuffer();");
                    }
                }

                //WriteComponents(ecsFile);

                for (var i = 0; i < ecsFile.buffers?.Count; i++)
                {
                    var b = ecsFile.buffers[i];
                    if (!b.flush)
                    {
                        WriteLine($"system.{b.name}.Execute(em);");
                    }
                }
                _indent--;
                WriteLine($"}}");
                WriteLine("partial void Execute(int length);");
                _indent--;
                WriteLine($"}}");

                WriteLine($"public sealed class {ecsFile.name}Processor : ISystem {{");
                _indent++;
                WriteLine($"public string Group => \"{ns}\";");
                WriteLine("private List<Dependency> _dependencies = null;");
                WriteLine("public IEnumerable<Dependency> Dependencies {");
                _indent++;
                WriteLine("if(_dependencies == null) {");
                _indent++;
                WriteLine("_dependencies = new List<Dependency>();");
                for (var i = 0; i < ecsFile.components?.Count; i++)
                {
                    var c    = ecsFile.components[i];
                    var type = $"Read";
                    if (c.write)
                    {
                        type = $"Write";
                    }

                    WriteLine($"_dependencies.Add(new {type}Dependency<{c.type}>());");
                }
                for (var i = 0; i < ecsFile.before?.Count; i++)
                {
                    WriteLine($"_dependencies.Add(new BeforeDependency>(\"{ecsFile.before[i]}\"));");
                }
                for (var i = 0; i < ecsFile.after?.Count; i++)
                {
                    WriteLine($"_dependencies.Add(new AfterDependency>(\"{ecsFile.after[i]}\"));");
                }
                // for (var i = 0; i < group.before?.Count; i++)
                //     WriteLine($"_dependencies.Add(new BeforeDependency>(\"{group.before[i]}\"));");
                // for (var i = 0; i < group.after?.Count; i++)
                //     WriteLine($"_dependencies.Add(new AfterDependency>(\"{group.after[i]}\"));");

                _indent--;
                WriteLine("}");
                WriteLine("return _dependencies;");
                _indent--;
                WriteLine("}");
                WriteLine($"public void Tick(SystemManager systemManager, EntityManager entityManager) => {ecsFile.name}.Process(systemManager, entityManager);");
                _indent--;
                WriteLine($"}}");
                _indent--;
                WriteLine($"}}");

                return(0);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                return(-1);
            }
            finally
            {
                if (!console)
                {
                    output.Dispose();
                }
            }
        }