Editor/sandmod.libraryplus/Library/Library.cs
using System;
using System.IO;
using System.Linq;
using System.Text.Json;
using Sandbox;

namespace LibraryPlus;

public abstract class Library
{
	internal Library( Package package, LibraryFileSystem fileSystem )
	{
		Package = package;
		FileSystem = fileSystem;
		ReadConfig();
		ReadVersion();
	}

	public LibraryConfig Config { get; private set; }
	public Version Version { get; private set; }

	public Package Package { get; }

	public LibraryFileSystem FileSystem { get; }

	public abstract bool IsPlus { get; }

	private void ReadConfig()
	{
		var configPath = Directory.EnumerateFiles( FileSystem.Settings.FullName, "*.sbproj" ).First();
		Config = JsonSerializer.Deserialize<LibraryConfig>( File.ReadAllText( configPath ) );
	}

	internal void SaveConfig()
	{
		var configPath = Directory.EnumerateFiles( FileSystem.Settings.FullName, "*.sbproj" ).First();
		File.WriteAllText( configPath, Config.ToJson() );
	}

	private void ReadVersion()
	{
		Version = new Version( 1, 0, 0 );
		var path = Path.Combine( FileSystem.Settings.FullName, ".version" );
		if ( !File.Exists( path ) || !Version.TryParse( File.ReadAllText( path ).Trim(), out var result ) )
		{
			return;
		}

		Version = result;
	}

	internal void Remove()
	{
		LibrarySystemPlus.Remove( this );
	}

	internal void UpdateReferenceFiles()
	{
		foreach ( var reference in Config.LibraryReferences )
		{
			var libraryIdent = reference.Key;
			UpdateReferenceLibrary( FileSystem.Code.FullName, libraryIdent );
			UpdateReferenceLibrary( FileSystem.Editor.FullName, libraryIdent );
		}
	}

	private void UpdateReferenceLibrary( string typePath, string library )
	{
		var directory = new DirectoryInfo( Path.Combine( typePath, "References", library ) );
		if ( !directory.Exists )
		{
			return;
		}

		foreach ( var file in directory.EnumerateFiles( "*.cs", SearchOption.AllDirectories ) )
		{
			UpdateReferenceFile( file.FullName, library );
		}
	}

	private void UpdateReferenceFile( string filePath, string library )
	{
		var preprocessor = $"LIBRARY_{library.ToUpper().Replace( ".", "_" )}";

		var define = $"#define {preprocessor}";
		var start = $"#if !{preprocessor}";
		var end = "#endif";

		var lines = File.ReadAllLines( filePath );
		var content = string.Join( Environment.NewLine, lines ).Replace( define, "" ).Replace( start, "" )
			.Replace( end, "" ).Trim();

		var newContent = $"{start}{Environment.NewLine}{content}{Environment.NewLine}{end}";
		if ( IsPlus && LibrarySystemPlus.AllPlus.Any( l => l.Package.ReferenceIdent() == library ) )
		{
			newContent = $"{define}{Environment.NewLine}{newContent}";
		}

		LibrarySystemPlus.WriteFileIfNeeded( filePath, newContent );
	}
}