/*
* GNU AFFERO GENERAL PUBLIC LICENSE
* Version 3, 19 November 2007
* Copyright (C) 2007 Free Software Foundation, Inc.
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.Linq;
using System.Reflection;
using UVtools.Core.Extensions;
using UVtools.Core.FileFormats;
namespace UVtools.Cmd.Symbols;
internal static class SetPropertiesCommand
{
internal static Command CreateCommand()
{
var propertiesArgument = new Argument("property=value", "Properties names and values to set")
{
Arity = ArgumentArity.OneOrMore
};
var layerRangeOption = new Option(new[] { "-r", "--range" }, "Sets properties to the matching layer(s) index(es) in a range")
{
ArgumentHelpName = "startindex:endindex"
};
var layerIndexesOption = new Option(new[] { "-i", "--indexes" }, "Sets properties to the matching layer(s) index(es)")
{
AllowMultipleArgumentsPerToken = true
};
var command = new Command("set-properties", "Set properties in a file or to it layers with new values")
{
GlobalArguments.InputFileArgument,
propertiesArgument,
layerRangeOption,
layerIndexesOption,
GlobalOptions.OutputFile,
};
command.SetHandler((inputFile, properties, layerRange, layerIndexes, outputFile) =>
{
var parsedProperties = new List(properties.Length);
foreach (var property in properties)
{
var split = property.Split(new[] { '=', ':' }, 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (split.Length < 2) continue;
parsedProperties.Add(new(split[0], split[1]));
}
if (parsedProperties.Count == 0)
{
Program.WriteLineError("No properties to set.");
}
var slicerFile = Program.OpenInputFile(inputFile, FileFormat.FileDecodeType.Partial);
var layerIndexesList = new List();
if (!string.IsNullOrWhiteSpace(layerRange))
{
if (slicerFile.TryParseLayerIndexRange(layerRange, out var layerIndexStart, out var layerIndexEnd))
{
for (var layerIndex = layerIndexStart; layerIndex <= layerIndexEnd; layerIndex++)
{
layerIndexesList.Add(layerIndex);
}
}
else
{
Program.WriteLineError($"The specified layer range '{layerRange}' is malformed, use startindex:endindex with positive numbers");
}
}
if (layerIndexes.Length > 0)
{
layerIndexesList.AddRange(layerIndexes.Select(layerIndex => slicerFile.SanitizeLayerIndex(layerIndex)));
}
layerIndexesList = layerIndexesList.Distinct().OrderBy(layerIndex => layerIndex).ToList();
uint setProperties = 0;
if (layerIndexesList.Count == 0)
{
foreach (var propertyInfo in slicerFile.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
foreach (var property in parsedProperties)
{
if (propertyInfo.Name != property.Name) continue;
propertyInfo.SetValueFromString(slicerFile, property.Value);
property.Found = true;
setProperties++;
}
}
}
else
{
foreach (var layerIndex in layerIndexesList)
{
var layer = slicerFile[layerIndex];
foreach (var propertyInfo in layer.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
foreach (var property in parsedProperties)
{
if (propertyInfo.Name != property.Name) continue;
propertyInfo.SetValueFromString(layer, property.Value);
property.Found = true;
setProperties++;
}
}
}
}
foreach (var property in parsedProperties)
{
if (property.Found) continue;
Program.WriteLineWarning($"Property {property.Name} was defined but not found nor set.");
}
if (setProperties <= 0) return;
Program.WriteLine($"Properties set: {setProperties}");
Program.SaveFile(slicerFile, outputFile);
}, GlobalArguments.InputFileArgument, propertiesArgument, layerRangeOption, layerIndexesOption, GlobalOptions.OutputFile);
return command;
}
}