<?php

 
 
// Staring deep into abyss... oh please, oh please

error_reporting(-1);

//tools
// tool 1, function to pick form

function doFormCheck($input,$i) {
    $form=NULL;
    $arrayOfForms=array
        (
        0=>array('single'=>'рубль','plural'=>'рублей','special'=>'рубля'),
        1=>array('single'=>'тысяча','plural'=>'тысяч','special'=>'тысячи'),
        2=>array('single'=>'миллион','plural'=>'миллионов','special'=>'миллиона'),
        );
    
    // ^this is also map for our numbers layout. 0 roubles 1 thousands 2 millions
    
    //main code identifying form
    
    if ( ($input-1) % 10 == 0 && ($input % 100) !== 11) {
        
        //number ends with 1 except 11
        
        $form= "single";
        }
    
    elseif (!($input % 10)) {
        
        //number ends with 0
        
        $form="plural";
        
    }
    elseif (round($input / 10) == floor ($input / 10) && !in_array($input % 100, [11,12,13,14])) {
        
        //ends with 1-4 but 1 is omitted because of first condiition check (as is omitted 0)
        
        $form="special";
        
        }
    
    else {
        
        //number ends with 5-9
        
        $form= "plural";
        
        }
    
    return $arrayOfForms[$i][$form];
}
    
    
// tool 2, function to lookup last 3 digits of any given number

function identifyLastThreeDigits($input) {
    
    return $input % 1000;
}
   
//tool 3, function to split complex numbers into array of triplets

function doTriplets($input) {
    $arrayOfTriplets=[];
    
    while (identifyLastThreeDigits($input)!==$input) {
        
        //number has > 3 digits
        
        array_push($arrayOfTriplets,identifyLastThreeDigits($input));
        $input = intval(floor($input / 1000));
        
          /*
        
        intval() is used here because floor from float produces float. Remainder of float / 1000 will be int. Thus the loop condition !==
        in the head will be evaluated as int vs float comparison, thus falling to infinitive cycle 
        
        this could be bypassed by either covert coercion in the head of loop != instead of strict !==
        or by overt coercion with inval(). i chose the second
        
        */
    }
    
    //now number has <= 3 digits
    
    array_push($arrayOfTriplets, $input);
    
    return $arrayOfTriplets;
}
        
        
//tool 4, function to convert arrayofnumbers into a string while picking form with tool1 in a process

function doStringify($arrayOfNumbers) {
    
    $arrayOfStrings = [];
    
    
    $maleSpelling = array(
        
        0   =>  'ноль',                                     10  =>  'десять',       100 =>  'сто',
        1   =>  'один',         11  =>  'одиннадцать',      20  =>  'двадцать',     200 =>  'двести',
        2   =>  'два',          12  =>  'двенадцать',       30  =>  'тридцать',     300 =>  'триста',
        3   =>  'три',          13  =>  'тринадцать',       40  =>  'сорок',        400 =>  'четыреста',
        4   =>  'четыре',       14  =>  'четырнадцать',     50  =>  'пятьдесят',    500 =>  'пятьсот',
        5   =>  'пять',         15  =>  'пятнадцать',       60  =>  'шестьдесят',   600 =>  'шестьсот',
        6   =>  'шесть',        16  =>  'шестнадцать',      70  =>  'семьдесят',    700 =>  'семьсот',    
        7   =>  'семь',         17  =>  'семнадцать',       80  =>  'восемьдесят',   800 =>  'восемьсот',
        8   =>  'восемь',       18  =>  'восемнадцать',     90  =>  'девяносто',     900 =>  'девятьсот',
        9   =>  'девять',       19  =>  'девятнадцать'
    );
    
    $femSpelling = array(
        
        1 => 'одна',
        2 => 'две',
        
        );
    
    for ($i=0;$i<count($arrayOfNumbers);$i++) {
        
        // remember layout: 0 roubles 1 thousands 2 millions
        
        $spelling = ($i == 1) ? ($femSpelling+$maleSpelling) : $maleSpelling;
        
        // general check for blanks begins
        
        // blanks will not be processed unless '0 roubles' (with 0 being omitted if not standalone)
        
        if ($arrayOfNumbers[$i]==0) {
            
            if ($i==0 && count($arrayOfNumbers) == 1) {
                $word = $spelling[$arrayOfNumbers[$i]];
                $word = $word . " " . doFormCheck($arrayOfNumbers[$i], $i);
                array_unshift($arrayOfStrings, $word);
            }
            elseif ($i==0 && count($arrayOfNumbers) > 1) {
                $word = " " . doFormCheck($arrayOfNumbers[$i], $i);
                array_unshift($arrayOfStrings, $word);
            }
            
            continue;
            
        }
        
        //general check for blanks ends
        
        //filling non-blanks begins
        
        
        if (isset($spelling[$arrayOfNumbers[$i]])) {
            
            //if number is mapped case
            
            $word = $spelling[$arrayOfNumbers[$i]];
            
            $word = $word . " " . doFormCheck($arrayOfNumbers[$i], $i);
                              
            array_unshift($arrayOfStrings, $word);
            
        }
        
        else {
            
            //if number is not a mapped case
            
            $componentHundreds=NULL;
            $componentTens=NULL;
            $componentPrimes=NULL;
            
            //cant use single word, need array of them
            
            $arrayOfWords=[];
            
            
            //preparing arrayOfWords
            
            if ($arrayOfNumbers[$i] < 100) {
                
                // number will have 2 components. componentHundreds remains NULL.
                
                $componentTens = floor($arrayOfNumbers[$i] / 10) * 10;
                $componentPrimes = $arrayOfNumbers[$i] - $componentTens;
                $arrayOfWords = [$spelling[$componentTens], $spelling[$componentPrimes]];
                
            }
            
            else {
                
                //number will have either 2 (remnant is mapped case) or 3 components
                
                $componentHundreds = floor($arrayOfNumbers[$i] / 100) * 100;
                $componentTens = $arrayOfNumbers[$i] - $componentHundreds;
                
                //if remnant is mapped case
                
                if (isset($spelling[$componentTens])) {
                    $arrayOfWords=[$spelling[$componentHundreds], $spelling[$componentTens]];
                    
                }
                
                // now if remnant is a mapped case having 2 components is enough. If not we must go deeper.
                
                elseif (!isset($spelling[$componentTens])) {
                    
                    //im using elseif for clarity
                    
                    $componentTens = floor($componentTens / 10) * 10;
                    $componentPrimes = $arrayOfNumbers[$i] - $componentHundreds - $componentTens;
                    $arrayOfWords=[$spelling[$componentHundreds], $spelling[$componentTens], $spelling[$componentPrimes]];
                    
                }
                    
                }
            
            // arrayOfWords prepared
                    
                
            $word = implode(" ", $arrayOfWords) . " " . doFormCheck($arrayOfNumbers[$i],$i); 
            
            // ^our doFormCheck() function can parse number as is, components not needed for it
                              
            array_unshift($arrayOfStrings, $word);
        }
    }

    
    return "". implode(" ", $arrayOfStrings);
    
}


//main function and launcher

function numberToText($input) {
    
    $arrayOfNumbers=[];
    
    //preparing array 
    
    if (identifyLastThreeDigits($input)==$input) {
       
       // number is already of <=3 digits
        
        array_push($arrayOfNumbers, $input);
        
    }
    
    elseif (identifyLastThreeDigits($input)!==$input) {
        
        // number has >3 digits
        
        $arrayOfNumbers = doTriplets($input);
    }
    
    //array prepared
    
    $string=doStringify($arrayOfNumbers);
    
    // insert amount in parenthesis
    
    $string=preg_replace('/\s(?=(рубл+))/u', " ({$input}) ", $string);
    
    echo "На Вашем счете {$string}";
}
 
$amount1 = mt_rand(1,99999999);
numberToText($amount1);

 
 
?>