public static string Serialize(MostWantedStreamingSection section)
 {
     return(JsonSerializer.Serialize(section, options));
 }
        public override void Save(string directory, string src)
        {
            var lxry       = Path.Combine(directory, this.LXRY);
            var streamlxry = Path.Combine(directory, this.STREAMLXRY);

            if (!File.Exists(lxry))
            {
                throw new FileNotFoundException($"File {lxry} does not exist");
            }

            this._directory = Path.Combine(directory, src);
            if (!Directory.Exists(this._directory))
            {
                throw new DirectoryNotFoundException($"Folder {this._directory} does not exist");
            }

            var sectionsPath = Path.Combine(this._directory, "Sections.end");

            if (!File.Exists(sectionsPath))
            {
                throw new FileNotFoundException($"Section.end file does not exist");
            }

            var sectionList = File.ReadAllLines(sectionsPath);

            if (sectionList is null || sectionList.Length < 1)
            {
                throw new Exception("Sections.end has no information");
            }
            if (sectionList[0] != "[VERSN5]")
            {
                throw new Exception("Sections.end file is not a Version 5 endscript");
            }

            var sectionNames = new List <string>(sectionList.Length);

            for (int i = 1; i < sectionList.Length; ++i)
            {
                var line = sectionList[i];
                if (String.IsNullOrWhiteSpace(line))
                {
                    continue;
                }
                sectionNames.Add(line);
            }

            this._sections = new MostWantedStreamingSection[sectionNames.Count];

            using (var bw = new BinaryWriter(File.Open(streamlxry, FileMode.Create, FileAccess.Write)))
            {
                for (int i = 0; i < sectionNames.Count; ++i)
                {
                    var dir      = Path.Combine(this._directory, sectionNames[i]);
                    var dataPath = Path.Combine(dir, "DATA.BIN");
                    var setsPath = Path.Combine(dir, "Settings.end");

                    var array   = File.ReadAllBytes(dataPath);
                    var section = MostWantedStreamingSection.Deserialize(File.ReadAllText(setsPath));

                    section.FileOffset     = (uint)bw.BaseStream.Position;
                    section.Size           = array.Length;
                    section.CompressedSize = array.Length;
                    bw.Write(array);
                    var mark = Options.Default.Watermark;
                    bw.GeneratePadding(mark, new Alignment(0x1000, Alignment.AlignmentType.Modular));
                    this._sections[i] = section;
                }
            }

            var mainFile = File.ReadAllBytes(lxry);

            using (var ms = new MemoryStream(mainFile))
                using (var br = new BinaryReader(ms))
                    using (var bw = new BinaryWriter(File.Open(lxry, FileMode.Create, FileAccess.Write)))
                    {
                        while (br.BaseStream.Position < br.BaseStream.Length)
                        {
                            var id     = br.ReadEnum <BinBlockID>();
                            var size   = br.ReadInt32();
                            var offset = br.BaseStream.Position;

                            if (id == BinBlockID.TrackStreamingSections)
                            {
                                bw.WriteEnum(id);
                                bw.Write(this._sections.Length * 0x5C);

                                for (int i = 0; i < this._sections.Length; ++i)
                                {
                                    bw.WriteUnmanaged(this._sections[i]);
                                }
                            }
                            else
                            {
                                bw.WriteEnum(id);
                                bw.Write(size);
                                bw.Write(br.ReadBytes(size));
                            }

                            br.BaseStream.Position = offset + size;
                        }
                    }
        }
        public override void Load(string directory, string dest)
        {
            var lxry       = Path.Combine(directory, this.LXRY);
            var streamlxry = Path.Combine(directory, this.STREAMLXRY);

            if (!File.Exists(lxry))
            {
                throw new FileNotFoundException($"File {lxry} does not exist");
            }
            if (!File.Exists(streamlxry))
            {
                throw new FileNotFoundException($"File {streamlxry} does not exist");
            }

            this._directory = Path.Combine(directory, dest);
            Directory.CreateDirectory(this._directory);

            using (var br = new BinaryReader(File.Open(lxry, FileMode.Open, FileAccess.Read)))
            {
                while (br.BaseStream.Position < br.BaseStream.Length)
                {
                    var id     = br.ReadEnum <BinBlockID>();
                    var size   = br.ReadInt32();
                    var offset = br.BaseStream.Position;

                    if (id == BinBlockID.TrackStreamingSections)
                    {
                        var count = size / 0x5C;
                        this._sections = new MostWantedStreamingSection[count];

                        for (int i = 0; i < count; ++i)
                        {
                            this._sections[i] = br.ReadUnmanaged <MostWantedStreamingSection>();
                        }
                    }

                    br.BaseStream.Position = offset + size;
                }
            }

            using (var br = new BinaryReader(File.Open(streamlxry, FileMode.Open, FileAccess.Read)))
            {
                for (int i = 0; i < this._sections.Length; ++i)
                {
                    var section   = this._sections[i];
                    var totalpath = Path.Combine(this._directory, section.GetName());
                    Directory.CreateDirectory(totalpath);

                    br.BaseStream.Position = section.FileOffset;
                    var array = br.ReadBytes(section.Size);

                    var dataPath = Path.Combine(totalpath, "DATA.BIN");
                    var setsPath = Path.Combine(totalpath, "Settings.end");

                    File.WriteAllBytes(dataPath, array);
                    File.WriteAllText(setsPath, MostWantedStreamingSection.Serialize(section));
                }
            }

            using (var sw = new StreamWriter(File.Open(Path.Combine(this._directory, "Sections.end"), FileMode.Create, FileAccess.Write)))
            {
                sw.WriteLine("[VERSN5]");
                sw.WriteLine();

                for (int i = 0; i < this._sections.Length; ++i)
                {
                    sw.WriteLine(this._sections[i].GetName());
                }
            }
        }