public static function getAvailName($dir, $refname = "", $refext = "")
    {
        // fixes arguments
        $dir = trim($dir);
        $refname = trim($refname);
        $refext = ltrim(trim($refext), ".");

        if (!is_dir($dir)) {
            throw new SysException("Directory not found: $dir");
        }

        // default refname
        if (Text::isEmpty($refname)) {
            $refname = "file";
        }

        // gets name and extension
        $refname = basename($refname);
        $pos = strrpos($refname, ".");
        $name = $refname;
        $ext = $refext;

        if ($pos !== false) {
            $name = substr($refname, 0, $pos);

            if (Text::isEmpty($refext)) {
                $ext = substr($refname, $pos + 1);
            }
        }

        // gets an available name
        for ($i = 0; $i < 100; $i++) {
            $basename = $i > 0
                ? Text::concat(".", $name . "_" . $i, $ext)
                : Text::concat(".", $name, $ext);
            $filename = SysFile::concat($dir, $basename);

            if (!is_file($filename)) {
                break;
            }
        }

        return $filename;
    }