/*
 * Copyright (C) Eugene 'Vindex' Stulin, 2025-2026
 *
 * Distributed under
 * the Boost Software License 1.0 or (at your option)
 * the GNU Lesser General Public License 3.0 or later.
 * This file is offered as-is, without any warranty.
 */

module oxfuse.utils;

import std.algorithm : among, map;
import std.array : array;
import std.ascii : isDigit;
import std.conv : to;
import std.range : empty;
import std.stdio;
import std.string : split;
import std.typecons;


private Tuple!(string, string) splitToDigitAndStringParts(string v) {
    size_t pos = 0;
    for (; pos < v.length; pos++) {
        if (isDigit(v[pos]) || v[pos] == '.') {
            continue;
        }
        break;
    }
    return tuple(v[0 .. pos], v[pos .. $]);
}


char compareVersions(string strV1, string strV2) {
    if (strV1 == strV2) {
        return '=';
    }
    Tuple!(string, string) v1Parts = splitToDigitAndStringParts(strV1);
    Tuple!(string, string) v2Parts = splitToDigitAndStringParts(strV2);

    uint[] v1DigPart = v1Parts[0].split('.').map!(a => a.to!uint).array;
    uint[] v2DigPart = v2Parts[0].split('.').map!(a => a.to!uint).array;
    string v1StrPart = v1Parts[1];
    string v2StrPart = v2Parts[1];
    if (v1DigPart > v2DigPart) {
        return '>';
    } else if (v1DigPart < v2DigPart) {
        return '<';
    } else if (!v1StrPart.empty || !v2StrPart.empty) {
        if (v1StrPart.empty) {
            return '>';
        } else if (v2StrPart.empty) {
            return '<';
        } else {
            return (v1Parts[1] > v2Parts[1]) ? '>' : '<';
        }
    }
    return '=';
}
unittest {
    assert(compareVersions("3.14", "3.20.5") == '<');
    assert(compareVersions("3.14.1", "3.14.0") == '>');
    assert(compareVersions("3.14.1", "3.14.1-rc1") == '>');
    assert(compareVersions("3.14.0-rc2", "3.14.1-rc1") == '<');
}


/// Exception for null pointers.
class NoData : Exception {
    this(string msg = "", string file = __FILE__, size_t line = __LINE__) {
        super(msg, file, line);
    }
}
