<?php

namespace App\Util;

class Random {
    
    /**
     * Generate a random string of given length from characters specified in the charlist.
     *
     * @param int $length
     * @param string $charlist
     * @return string
     */
    public static function generate(int $length = 10, string $charlist = '0-9a-z'): string {
        $characters = self::expandCharList($charlist);
        $randomString = '';

        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[random_int(0, strlen($characters) - 1)];
        }

        return $randomString;
    }

    /**
     * Generate a UUID.
     *
     * @param int $length
     * @return string
     */
    public static function uuid(int $length = 36): string {
        $pattern = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
        $characters = '0123456789abcdef';
        $uuid = '';

        for ($i = 0; $i < $length; $i++) {
            $char = $pattern[$i];
            if ($char === 'x') {
                $uuid .= $characters[random_int(0, 15)];
            } elseif ($char === 'y') {
                $uuid .= $characters[random_int(8, 11)];
            } else {
                $uuid .= $char;
            }
        }

        return $uuid;
    }

    /**
     * Expand a charlist that may contain intervals like '0-9' or 'A-Z'.
     *
     * @param string $charlist
     * @return string
     */
    private static function expandCharList(string $charlist): string {
        $expanded = '';
        $length = strlen($charlist);

        for ($i = 0; $i < $length; $i++) {
            if ($charlist[$i] === '-') {
                $start = ord($charlist[$i - 1]) + 1;
                $end = ord($charlist[$i + 1]);

                for ($j = $start; $j <= $end; $j++) {
                    $expanded .= chr($j);
                }
            } else {
                $expanded .= $charlist[$i];
            }
        }

        return $expanded;
    }
}
