using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FileManager
{
/// Get valid filename. Advanced features incl. parameterized template
public class FileNamingTemplate : NamingTemplate
{
/// Proposed file name with optional html-styled template tags.
public FileNamingTemplate(string template) : base(template) { }
/// Optional step 2: Replace all illegal characters with this. Default=
public string IllegalCharacterReplacements { get; set; }
/// Generate a valid path for this file or directory
public LongPath GetFilePath(bool returnFirstExisting = false)
{
int lastSlash = Template.LastIndexOf('\\');
var directoryName = lastSlash >= 0 ? Template[..(lastSlash + 1)] : string.Empty;
var filename = lastSlash >= 0 ? Template[(lastSlash + 1)..] : Template;
List filenameParts = new();
var paramReplacements = ParameterReplacements.ToDictionary(r => $"<{formatKey(r.Key)}>", r => formatValue(r.Value));
//Build the filename in parts, replacing replacement parameters with
//their values, and storing the parts in a list.
while(!string.IsNullOrEmpty(filename))
{
int openIndex = filename.IndexOf('<');
int closeIndex = filename.IndexOf('>');
if (openIndex == 0 && closeIndex > 0)
{
var key = filename[..(closeIndex + 1)];
if (paramReplacements.ContainsKey(key))
filenameParts.Add(new StringBuilder(paramReplacements[key]));
else
filenameParts.Add(new StringBuilder(key));
filename = filename[(closeIndex + 1)..];
}
else if (openIndex > 0 && closeIndex > openIndex)
{
var other = filename[..openIndex];
filenameParts.Add(new StringBuilder(other));
filename = filename[openIndex..];
}
else
{
filenameParts.Add(new StringBuilder(filename));
filename = string.Empty;
}
}
//Remove 1 character from the end of the longest filename part until
//the total filename is less than max filename length
while(filenameParts.Sum(p => p.Length) > LongPath.MaxFilenameLength)
{
int maxLength = filenameParts.Max(p => p.Length);
var maxEntry = filenameParts.First(p => p.Length == maxLength);
maxEntry.Remove(maxLength - 1, 1);
}
filename = string.Join("", filenameParts);
return FileUtility.GetValidFilename(directoryName + filename, IllegalCharacterReplacements, returnFirstExisting);
}
private string formatValue(object value)
{
if (value is null)
return "";
// Other illegal characters will be taken care of later. Must take care of slashes now so params can't introduce new folders.
// Esp important for file templates.
return value
.ToString()
.Replace($"{System.IO.Path.DirectorySeparatorChar}", IllegalCharacterReplacements)
.Replace($"{System.IO.Path.AltDirectorySeparatorChar}", IllegalCharacterReplacements);
}
}
}