<?php

    $use_json_cache 
= ($argc 2);

    if(
file_exists("installed.json") AND $use_json_cache)
    {
        
$installed json_decode(file_get_contents("installed.json"), TRUE);
    }
    else
    {
        
$cmd 'apt --installed list 2>/dev/null | grep "/" | sed -e "s/\/.*//"';
        
$installed array_filter(explode("\n"shell_exec($cmd)));
        
file_put_contents("installed.json"json_encode($installedJSON_PRETTY_PRINT));
    }

    
$installed array_combine($installed$installed);

    
$world = array();
    
$world_dep = array();
    
$other_dep $installed;

    if(
file_exists("deps.json") AND file_exists("rdeps.json") AND $use_json_cache)
    {
        
$deps json_decode(file_get_contents("deps.json"), TRUE);
        
$rdeps json_decode(file_get_contents("rdeps.json"), TRUE);
        
$recomendations json_decode(file_get_contents("recomendations.json"), TRUE);
    }
    else
    {
        
$deps = array();
        
$rdeps = array();
        
$recomendations = array();
        foreach(
$installed as $package)
        {
            
$cmd 'apt-cache depends ' escapeshellarg($package) . ' 2>/dev/null';
            
$dep_text explode("\n"shell_exec($cmd));
            foreach(
$dep_text as $dep_row)
            {
                
$dep_columns explode(":"$dep_row3);
                if(empty(
$dep_columns[1])) continue;
                if(
substr($dep_columns[0], 04) == '    ') continue;

                
$dep trim($dep_columns[1]);
                switch(
trim($dep_columns[0], " \t\r\n|"))
                {
                    case 
'Depends':
                    case 
'PreDepends':
                    {
                        
// ok
                        
$deps[$package][$dep] = $dep;
                        
$rdeps[$dep][$package] = $package;
                        break;
                    }

                    case 
'Suggests':
                    case 
'Recommends':
                    case 
'Enhances':
                    {
                        
$recomendations[$dep][$package] = $package;
                        
// skip
                    
}

                    case 
'Replaces':
                    case 
'Conflicts':
                    case 
'Breaks':
                    {
                        
//skip
                        
continue;
                    }

                    default:
                    {
                        echo 
"bad dep-type: {$dep_columns[0]} in {$package}\n";
                        continue;
                    }
                }

// TODO                if(!isset($installed[$dep])) { echo "missing dep: " . $dep . " in " . $package . PHP_EOL; continue;}
            
}
        }

        
file_put_contents("deps.json"json_encode(array_map('array_values'$deps), JSON_PRETTY_PRINT));
        
file_put_contents("rdeps.json"json_encode(array_map('array_values'$rdeps), JSON_PRETTY_PRINT));
        
file_put_contents("recomendations.json"json_encode(array_map('array_values'$recomendations), JSON_PRETTY_PRINT));
    }

    foreach(
$installed as $package)
    {
        if(empty(
$rdeps[$package]))
        {
            
$world[$package] = $package;
            unset(
$other_dep[$package]);
        }
        else
        {
            
$rdeps[$package] = array_combine($rdeps[$package], $rdeps[$package]);
        }

        if(!empty(
$deps[$package]))
        {
            
$deps[$package] = array_combine($deps[$package], $deps[$package]);
        }
    }

    
$todo $world;
    while(
$package array_pop($todo))
    {
        if(empty(
$deps[$package])) continue;

        foreach(
$deps[$package] as $dep)
        {
            if(isset(
$world[$dep])) continue;
            if(isset(
$world_dep[$dep])) continue;

            
$todo[$dep] = $dep;
            
$world_dep[$dep] = $dep;
            unset(
$other_dep[$dep]);
        }
    }

    
$loops_dep = array();
    foreach(
$other_dep as $package)
    {
        foreach(
$deps[$package] as $dep)
        {
            if(isset(
$deps[$dep][$package]))
            {
                echo 
"Dep-Loop: {$dep} <-> {$package}\n";
                
$loops_dep[$package] = $dep;
                
$loops_dep[$dep] = $package;
                unset(
$other_dep[$dep]);
                unset(
$other_dep[$package]);
            }
        }
    }

    
$todo $loops_dep;
    while(
$package array_pop($todo))
    {
        if(empty(
$deps[$package])) continue;

        foreach(
$deps[$package] as $dep)
        {
            if(isset(
$world[$dep])) continue;
            if(isset(
$world_dep[$dep])) continue;
            if(isset(
$loops_dep[$dep])) continue;

            
$todo[$dep] = $dep;
            
$world_dep[$dep] = $dep;
            unset(
$other_dep[$dep]);
        }
    }

    
$preinstalled = array();
    
$added = array();
    
$removed = array();
    if(
file_exists('preinstalled.txt'))
    {
        
$preinstalled array_filter(array_map("trim"explode("\n"file_get_contents("preinstalled.txt"))));
        
file_put_contents("preinstalled.json"json_encode($preinstalledJSON_PRETTY_PRINT));

        
$preinstalled array_combine($preinstalled$preinstalled);

        foreach(
$preinstalled as $package)
        {
            if(empty(
$installed[$package]))
            {
                
$removed[$package] = $package;
            }
        }

        foreach(
$world as $package)
        {
            if(empty(
$preinstalled[$package]))
            {
                
$added[$package] = $package;
            }
        }

        
file_put_contents("added.json"json_encode($addedJSON_PRETTY_PRINT));
        
file_put_contents("removed.json"json_encode($removedJSON_PRETTY_PRINT));
    }


//     echo "World:\n"; print_r($world);
    
file_put_contents("world.json"json_encode($worldJSON_PRETTY_PRINT));
// //    echo "World Dep:\n"; print_r($world_dep);
    
file_put_contents("world_dep.json"json_encode(array_values($world_dep), JSON_PRETTY_PRINT));
    if(
$other_dep) {echo "Unknown dep:\n"print_r($other_dep);}
    
file_put_contents("other.json"json_encode(array_values($other_dep), JSON_PRETTY_PRINT));
//
    
print_r(array(
            
'installed' => count($installed),
            
'world' => count($world),
            
'loops_dep' => count($loops_dep),
            
'world_dep' => count($world_dep),
            
'other' => count($other_dep),
            
'preinstalled' => count($preinstalled),
            
'added' => count($added),
            
'removed' => count($removed),
        ));

    
$texts = array('r' => array(), 'm' => array());
    foreach(
$added as $package)
    {
        if(empty(
$recomendations[$package]))
        {
            
$texts['m'][] = $package;
        }
        else
        {
            
$texts['r'][] = $package " (recomendated by: " implode(", "$recomendations[$package]) . ")";
        }
    }

    if(
$texts['r'])
    {
        echo 
"\nInstalled Recomendation:\n" implode("\n"$texts['r']) . PHP_EOL;
    }

    if(
$texts['m'])
    {
        echo 
"\nManual installations:\n" implode("\n"$texts['m']) . PHP_EOL;
        
file_put_contents("manual.json"json_encode($texts['m'], JSON_PRETTY_PRINT));
    }