<?php
/**
 * File: view_structure.php
 * Fungsi: Melihat struktur file dan folder secara dinamis
 * File ini akan mendeteksi lokasinya sendiri dan menampilkan struktur dari direktori tersebut
 */

// Mendapatkan direktori dimana file ini berada
$currentDir = __DIR__;

// Deteksi path relatif dari root website
$documentRoot = $_SERVER['DOCUMENT_ROOT'];
$relativePath = str_replace($documentRoot, '', $currentDir);
$relativePath = str_replace('\\', '/', $relativePath);

// Parameter untuk kedalaman scan (default: semua level)
$maxDepth = isset($_GET['depth']) ? intval($_GET['depth']) : -1; // -1 = unlimited
$showHidden = isset($_GET['hidden']) ? true : false;
$searchTerm = isset($_GET['search']) ? trim($_GET['search']) : '';

// Tentukan direktori yang akan di-scan (bisa dari parameter atau default)
$scanDir = isset($_GET['dir']) ? $_GET['dir'] : $currentDir;

// Validasi direktori
if (!is_dir($scanDir)) {
    die("Direktori tidak ditemukan: " . htmlspecialchars($scanDir));
}

// Security: pastikan direktori masih di dalam document root
$realScanDir = realpath($scanDir);
$realDocumentRoot = realpath($documentRoot);
if (strpos($realScanDir, $realDocumentRoot) !== 0) {
    die("Akses ke direktori di luar document root tidak diizinkan.");
}

/**
 * Fungsi untuk mendapatkan struktur direktori secara rekursif
 * 
 * @param string $dir Path direktori
 * @param int $level Level indentasi
 * @param int $maxDepth Maksimum kedalaman
 * @param bool $showHidden Tampilkan file hidden
 * @param string $searchTerm Filter pencarian
 * @return array Array struktur direktori
 */
function getDirectoryStructure($dir, $level = 0, $maxDepth = -1, $showHidden = false, $searchTerm = '') {
    $structure = [];
    
    // Cek kedalaman
    if ($maxDepth !== -1 && $level >= $maxDepth) {
        return $structure;
    }
    
    // Baca semua file dan folder dalam direktori
    $items = scandir($dir);
    if ($items === false) {
        return $structure;
    }
    
    // Filter hidden files
    if (!$showHidden) {
        $items = array_filter($items, function($item) {
            return $item[0] !== '.';
        });
    }
    
    // Filter . dan ..
    $items = array_filter($items, function($item) {
        return $item !== '.' && $item !== '..';
    });
    
    // Filter berdasarkan pencarian
    if (!empty($searchTerm)) {
        $items = array_filter($items, function($item) use ($searchTerm) {
            return stripos($item, $searchTerm) !== false;
        });
    }
    
    // Sortir items (folder dulu, kemudian file)
    $folders = [];
    $files = [];
    
    foreach ($items as $item) {
        $fullPath = $dir . DIRECTORY_SEPARATOR . $item;
        if (is_dir($fullPath)) {
            $folders[] = $item;
        } else {
            $files[] = $item;
        }
    }
    
    sort($folders, SORT_STRING | SORT_FLAG_CASE);
    sort($files, SORT_STRING | SORT_FLAG_CASE);
    $items = array_merge($folders, $files);
    
    // Proses setiap item
    foreach ($items as $item) {
        $fullPath = $dir . DIRECTORY_SEPARATOR . $item;
        
        // Dapatkan timestamp modifikasi
        $modifiedTime = filemtime($fullPath);
        
        if (is_dir($fullPath)) {
            // Ini adalah folder
            $children = getDirectoryStructure($fullPath, $level + 1, $maxDepth, $showHidden, $searchTerm);
            $structure[] = [
                'type' => 'folder',
                'name' => $item,
                'path' => $fullPath,
                'level' => $level,
                'modified' => date('Y-m-d H:i:s', $modifiedTime),
                'children' => $children,
                'childCount' => count($children)
            ];
        } else {
            // Ini adalah file
            $fileSize = filesize($fullPath);
            $extension = pathinfo($item, PATHINFO_EXTENSION);
            $structure[] = [
                'type' => 'file',
                'name' => $item,
                'path' => $fullPath,
                'level' => $level,
                'size' => formatFileSize($fileSize),
                'sizeBytes' => $fileSize,
                'extension' => $extension,
                'modified' => date('Y-m-d H:i:s', $modifiedTime),
                'isImage' => in_array(strtolower($extension), ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp']),
                'isCode' => in_array(strtolower($extension), ['php', 'html', 'css', 'js', 'json', 'xml', 'sql'])
            ];
        }
    }
    
    return $structure;
}

/**
 * Fungsi untuk format ukuran file
 */
function formatFileSize($bytes) {
    if ($bytes === 0) return '0 B';
    
    $units = ['B', 'KB', 'MB', 'GB', 'TB'];
    $i = floor(log($bytes, 1024));
    $size = round($bytes / pow(1024, $i), 2);
    
    return $size . ' ' . $units[$i];
}

/**
 * Fungsi untuk mendapatkan warna berdasarkan ekstensi file
 */
function getFileColor($extension) {
    $colors = [
        'php' => '#4F5D95',
        'html' => '#E34C26',
        'htm' => '#E34C26',
        'css' => '#563D7C',
        'js' => '#F1E05A',
        'json' => '#000000',
        'txt' => '#333333',
        'md' => '#083FA1',
        'sql' => '#003B6F',
        'xml' => '#006400',
        'png' => '#A8B9C0',
        'jpg' => '#A8B9C0',
        'jpeg' => '#A8B9C0',
        'gif' => '#A8B9C0',
        'svg' => '#FF9900',
        'ico' => '#FF6B6B',
        'pdf' => '#B22222',
        'zip' => '#D4A843',
        'rar' => '#D4A843',
        'tar' => '#D4A843',
        'gz' => '#D4A843',
        'exe' => '#8B0000',
        'bat' => '#8B0000',
        'sh' => '#8B0000',
        'log' => '#808080',
        'env' => '#2E8B57',
        'yml' => '#2E8B57',
        'yaml' => '#2E8B57'
    ];
    
    return isset($colors[strtolower($extension)]) ? $colors[strtolower($extension)] : '#000000';
}

/**
 * Fungsi untuk mendapatkan icon berdasarkan tipe file
 */
function getFileIcon($item) {
    if ($item['type'] === 'folder') {
        return '📁';
    }
    
    $ext = strtolower($item['extension']);
    $icons = [
        'php' => '🐘',
        'html' => '🌐',
        'htm' => '🌐',
        'css' => '🎨',
        'js' => '⚡',
        'json' => '📋',
        'txt' => '📄',
        'md' => '📝',
        'sql' => '🗄️',
        'xml' => '📰',
        'png' => '🖼️',
        'jpg' => '🖼️',
        'jpeg' => '🖼️',
        'gif' => '🖼️',
        'svg' => '🖼️',
        'ico' => '🖼️',
        'pdf' => '📕',
        'zip' => '📦',
        'rar' => '📦',
        'exe' => '⚙️',
        'bat' => '⚙️',
        'sh' => '⚙️'
    ];
    
    return isset($icons[$ext]) ? $icons[$ext] : '📄';
}

/**
 * Fungsi untuk menampilkan struktur dalam bentuk tree dengan HTML
 */
function displayTree($structure, $prefix = '', $isLast = true, $level = 0) {
    $lastIndex = count($structure) - 1;
    $currentLevel = $level;
    
    foreach ($structure as $index => $item) {
        $isLastItem = ($index === $lastIndex);
        $branch = $isLastItem ? '└── ' : '├── ';
        $childPrefix = $isLastItem ? '    ' : '│   ';
        
        // Tambahkan prefix dengan indentasi
        $indent = '';
        for ($i = 0; $i < $level; $i++) {
            $indent .= '│   ';
        }
        
        // Tampilkan item
        if ($item['type'] === 'folder') {
            $icon = '📁';
            echo '<div class="tree-item">';
            echo $indent . $branch . '<span class="folder" onclick="toggleFolder(this)" data-path="' . htmlspecialchars($item['path']) . '">';
            echo $icon . ' <strong>' . htmlspecialchars($item['name']) . '</strong>';
            if ($item['childCount'] > 0) {
                echo ' <span class="badge">' . $item['childCount'] . ' items</span>';
            }
            echo ' <span class="modified">🕐 ' . $item['modified'] . '</span>';
            echo '</span>';
            echo '</div>';
            
            // Proses child folder dengan level yang lebih tinggi
            if (!empty($item['children'])) {
                echo '<div class="children" style="display: block;">';
                displayTree($item['children'], '', $isLastItem, $level + 1);
                echo '</div>';
            }
        } else {
            $icon = getFileIcon($item);
            $color = getFileColor($item['extension']);
            
            echo '<div class="tree-item file-item">';
            echo $indent . $branch . '<span style="color: ' . $color . ';">';
            echo $icon . ' ' . htmlspecialchars($item['name']);
            echo ' <span class="file-size">(' . $item['size'] . ')</span>';
            echo ' <span class="modified">🕐 ' . $item['modified'] . '</span>';
            echo '</span>';
            echo '</div>';
        }
    }
}

/**
 * Fungsi untuk menampilkan statistik
 */
function displayStatistics($structure, $path) {
    $totalFiles = 0;
    $totalFolders = 0;
    $totalSize = 0;
    $fileTypes = [];
    $largeFiles = [];
    
    function countItems($items, &$totalFiles, &$totalFolders, &$totalSize, &$fileTypes, &$largeFiles) {
        foreach ($items as $item) {
            if ($item['type'] === 'folder') {
                $totalFolders++;
                if (!empty($item['children'])) {
                    countItems($item['children'], $totalFiles, $totalFolders, $totalSize, $fileTypes, $largeFiles);
                }
            } else {
                $totalFiles++;
                $totalSize += $item['sizeBytes'];
                
                $ext = $item['extension'];
                if (!isset($fileTypes[$ext])) {
                    $fileTypes[$ext] = 0;
                }
                $fileTypes[$ext]++;
                
                // File besar (> 1MB)
                if ($item['sizeBytes'] > 1024 * 1024) {
                    $largeFiles[] = $item;
                }
            }
        }
    }
    
    countItems($structure, $totalFiles, $totalFolders, $totalSize, $fileTypes, $largeFiles);
    
    echo '<div class="stats">';
    echo '<h3>📊 Statistik</h3>';
    echo '<div class="stats-grid">';
    echo '<div class="stat-item"><span class="stat-label">📁 Total Folder</span><span class="stat-value">' . number_format($totalFolders) . '</span></div>';
    echo '<div class="stat-item"><span class="stat-label">📄 Total File</span><span class="stat-value">' . number_format($totalFiles) . '</span></div>';
    echo '<div class="stat-item"><span class="stat-label">💾 Total Ukuran</span><span class="stat-value">' . formatFileSize($totalSize) . '</span></div>';
    echo '<div class="stat-item"><span class="stat-label">📂 Direktori</span><span class="stat-value" style="font-size: 0.8em;">' . htmlspecialchars($path) . '</span></div>';
    echo '</div>';
    
    // Tipe file terbanyak
    if (!empty($fileTypes)) {
        arsort($fileTypes);
        echo '<div class="file-types">';
        echo '<h4>🔝 Top Ekstensi File</h4>';
        echo '<ul>';
        $count = 0;
        foreach ($fileTypes as $ext => $countType) {
            if ($count++ >= 10) break;
            $extDisplay = empty($ext) ? 'tanpa ekstensi' : '.' . $ext;
            $color = getFileColor($ext);
            echo '<li><span style="color: ' . $color . ';">' . $extDisplay . '</span>: ' . $countType . ' file</li>';
        }
        echo '</ul>';
        echo '</div>';
    }
    
    // File besar
    if (!empty($largeFiles)) {
        echo '<div class="large-files">';
        echo '<h4>📦 File Besar (>1MB)</h4>';
        echo '<ul>';
        usort($largeFiles, function($a, $b) {
            return $b['sizeBytes'] - $a['sizeBytes'];
        });
        foreach (array_slice($largeFiles, 0, 10) as $file) {
            echo '<li>' . htmlspecialchars($file['name']) . ' (' . $file['size'] . ')</li>';
        }
        echo '</ul>';
        echo '</div>';
    }
    
    echo '</div>';
}

// Proses utama
$structure = getDirectoryStructure($scanDir, 0, $maxDepth, $showHidden, $searchTerm);

?>
<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Explorer - <?php echo basename($scanDir); ?></title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #f0f2f5;
            padding: 20px;
        }
        
        .container {
            max-width: 1400px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 12px;
            box-shadow: 0 2px 20px rgba(0,0,0,0.1);
        }
        
        .header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
            gap: 15px;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #e8ecf1;
        }
        
        h1 {
            color: #1a2332;
            font-size: 24px;
        }
        
        .path-info {
            background: #f8f9fa;
            padding: 12px 18px;
            border-radius: 8px;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            word-break: break-all;
            border-left: 4px solid #4a90d9;
        }
        
        .controls {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            margin: 15px 0;
            padding: 15px;
            background: #f8f9fa;
            border-radius: 8px;
        }
        
        .controls input, .controls select {
            padding: 8px 12px;
            border: 1px solid #ddd;
            border-radius: 5px;
            font-size: 14px;
        }
        
        .controls button {
            padding: 8px 16px;
            background: #4a90d9;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
        }
        
        .controls button:hover {
            background: #357abd;
        }
        
        .controls label {
            display: flex;
            align-items: center;
            gap: 5px;
            font-size: 14px;
        }
        
        .tree-container {
            background: #fafbfc;
            border: 1px solid #e8ecf1;
            border-radius: 8px;
            padding: 20px;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            line-height: 1.8;
            overflow-x: auto;
            max-height: 600px;
            overflow-y: auto;
        }
        
        .tree-item {
            white-space: nowrap;
        }
        
        .folder {
            cursor: pointer;
            color: #1a2332;
            font-weight: 500;
        }
        
        .folder:hover {
            background: #e8ecf1;
            border-radius: 3px;
            padding: 0 4px;
        }
        
        .children {
            padding-left: 20px;
        }
        
        .badge {
            background: #4a90d9;
            color: white;
            font-size: 10px;
            padding: 2px 8px;
            border-radius: 10px;
            margin-left: 5px;
        }
        
        .file-size {
            color: #888;
            font-size: 0.85em;
        }
        
        .modified {
            color: #999;
            font-size: 0.8em;
            margin-left: 10px;
        }
        
        .stats {
            margin-top: 25px;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 8px;
        }
        
        .stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            margin: 15px 0;
        }
        
        .stat-item {
            background: white;
            padding: 12px;
            border-radius: 6px;
            border: 1px solid #e8ecf1;
        }
        
        .stat-label {
            display: block;
            font-size: 12px;
            color: #888;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }
        
        .stat-value {
            display: block;
            font-size: 18px;
            font-weight: 600;
            color: #1a2332;
            margin-top: 5px;
        }
        
        .file-types, .large-files {
            margin-top: 15px;
        }
        
        .file-types ul, .large-files ul {
            list-style: none;
            padding: 0;
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
            gap: 5px;
        }
        
        .file-types li, .large-files li {
            padding: 5px 10px;
            background: white;
            border-radius: 4px;
            border: 1px solid #e8ecf1;
            font-size: 13px;
        }
        
        .breadcrumb {
            padding: 10px 0;
            color: #666;
            font-size: 14px;
        }
        
        .breadcrumb a {
            color: #4a90d9;
            text-decoration: none;
        }
        
        .breadcrumb a:hover {
            text-decoration: underline;
        }
        
        .footer-actions {
            margin-top: 20px;
            display: flex;
            gap: 10px;
            justify-content: center;
        }
        
        .footer-actions a {
            padding: 10px 20px;
            background: #4a90d9;
            color: white;
            border-radius: 5px;
            text-decoration: none;
        }
        
        .footer-actions a:hover {
            background: #357abd;
        }
        
        @media (max-width: 768px) {
            .container {
                padding: 15px;
            }
            .controls {
                flex-direction: column;
            }
            .header {
                flex-direction: column;
                align-items: stretch;
            }
            .tree-container {
                font-size: 12px;
                max-height: 400px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>📂 File Explorer</h1>
            <div class="path-info">
                📍 <?php echo htmlspecialchars($scanDir); ?>
            </div>
        </div>
        
        <div class="breadcrumb">
            <?php
            $parts = explode('/', str_replace('\\', '/', $scanDir));
            $currentPath = '';
            foreach ($parts as $index => $part) {
                $currentPath .= $part . '/';
                if ($index == count($parts) - 1) {
                    echo '<strong>' . htmlspecialchars($part) . '</strong>';
                } else {
                    echo '<a href="?dir=' . urlencode(rtrim($currentPath, '/')) . '">' . htmlspecialchars($part) . '</a> / ';
                }
            }
            ?>
        </div>
        
        <form method="GET" class="controls">
            <input type="text" name="search" placeholder="🔍 Cari file/folder..." value="<?php echo htmlspecialchars($searchTerm); ?>">
            
            <select name="depth">
                <option value="-1" <?php echo $maxDepth == -1 ? 'selected' : ''; ?>>Semua Level</option>
                <option value="0" <?php echo $maxDepth == 0 ? 'selected' : ''; ?>>Level 0</option>
                <option value="1" <?php echo $maxDepth == 1 ? 'selected' : ''; ?>>Level 1</option>
                <option value="2" <?php echo $maxDepth == 2 ? 'selected' : ''; ?>>Level 2</option>
                <option value="3" <?php echo $maxDepth == 3 ? 'selected' : ''; ?>>Level 3</option>
                <option value="4" <?php echo $maxDepth == 4 ? 'selected' : ''; ?>>Level 4</option>
                <option value="5" <?php echo $maxDepth == 5 ? 'selected' : ''; ?>>Level 5</option>
            </select>
            
            <label>
                <input type="checkbox" name="hidden" value="1" <?php echo $showHidden ? 'checked' : ''; ?>>
                Tampilkan Hidden
            </label>
            
            <button type="submit">🔍 Tampilkan</button>
            <button type="button" onclick="window.location.href=''">🔄 Reset</button>
        </form>
        
        <?php if (empty($structure)): ?>
            <div style="padding: 20px; text-align: center; color: #999;">
                <?php if (!empty($searchTerm)): ?>
                    Tidak ada hasil untuk pencarian "<?php echo htmlspecialchars($searchTerm); ?>"
                <?php else: ?>
                    Folder kosong atau tidak ada item yang ditemukan.
                <?php endif; ?>
            </div>
        <?php else: ?>
            <div class="tree-container" id="treeContainer">
                <?php displayTree($structure); ?>
            </div>
            
            <?php displayStatistics($structure, $scanDir); ?>
        <?php endif; ?>
        
        <div class="footer-actions">
            <a href="?">🔄 Refresh</a>
            <a href="#" onclick="window.print(); return false;">🖨️ Print</a>
            <a href="#" onclick="exportTree(); return false;">📥 Export Tree</a>
        </div>
    </div>
    
    <script>
        // Fungsi toggle folder
        function toggleFolder(element) {
            const children = element.closest('.tree-item').nextElementSibling;
            if (children && children.classList.contains('children')) {
                if (children.style.display === 'none') {
                    children.style.display = 'block';
                    element.innerHTML = element.innerHTML.replace('📂', '📁');
                } else {
                    children.style.display = 'none';
                    element.innerHTML = element.innerHTML.replace('📁', '📂');
                }
            }
        }
        
        // Fungsi export tree
        function exportTree() {
            const treeContainer = document.getElementById('treeContainer');
            const text = treeContainer.innerText;
            const blob = new Blob([text], { type: 'text/plain' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'tree_structure.txt';
            a.click();
            URL.revokeObjectURL(url);
        }
        
        // Auto expand folder yang memiliki child
        document.addEventListener('DOMContentLoaded', function() {
            // Semua folder yang memiliki child akan otomatis terbuka
            document.querySelectorAll('.folder').forEach(function(element) {
                const children = element.closest('.tree-item').nextElementSibling;
                if (children && children.classList.contains('children')) {
                    const badge = element.querySelector('.badge');
                    if (badge && parseInt(badge.textContent) > 0) {
                        // Biarkan terbuka secara default
                        children.style.display = 'block';
                    }
                }
            });
        });
    </script>
</body>
</html>