namespace InnovEnergy.SysTools.Utils;

public static class Utils
{
    public static IEnumerable<T> Traverse<T>(T root, Func<T, IEnumerable<T>> getChildren)
    {
        var stack = new Stack<IEnumerator<T>>();
        var it    = root.Enumerator();
        it.MoveNext();

        while (true)
        {
            //////// going down ////////

            while (true)
            {
                var cit = getChildren(it.Current).GetEnumerator();

                if (cit.MoveNext())  // node has children, must be a branch
                {
                    yield return it.Current;

                    stack.Push(it);
                    it = cit;
                }
                else // no children, hence a leaf
                {
                    var node = it.Current;

                    yield return node;

                    if (!it.MoveNext())
                        break; // no more siblings: goto parent
                }
            }

            //////// going up ////////

            while (true)
            {
                it.Dispose();
                if (stack.Count == 0) yield break; // we got to the bottom of the stack, were done

                it = stack.Pop();

                if (it.MoveNext())
                    break;
            }
        }


    }


    private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public static DateTime FromUnixTime(UInt64 unixTime)
    {
        return Epoch.AddSeconds(unixTime);
    }


    public static R ValueOrDefault<T, R>(this Dictionary<T, R> dict, T key)
    {
        return ValueOrDefault(dict, key, default);
    }

    public static R ValueOrDefault<T, R>(this Dictionary<T, R> dict, T key, R defaultValue)
    {
        return dict.TryGetValue(key, out var value) ? value : defaultValue;
    }

    public static void CopyFilesRecursively(String source, String target)
    {
        CopyFilesRecursively(new DirectoryInfo(source), new DirectoryInfo(target));
    }

    public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
    {
        foreach (var file in source.GetFiles())
            file.CopyTo(Path.Combine(target.FullName, file.Name));

        foreach (var dir in source.GetDirectories())
            CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
    }

}