
<?php
/* ============================================================
   UNIVERSAL WYSIWYG → APK EXPORTER (SINGLE FILE)
   - Visual drag & drop editor
   - Multi‑page apps
   - Live preview
   - No assumptions about app type
   - Exports packaged APK (ZIP-based placeholder)
   ============================================================ */

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['export'])) {
    $appName   = preg_replace('/[^a-zA-Z0-9 _-]/', '', $_POST['app_name'] ?? 'MyApp');
    $packageId = preg_replace('/[^a-zA-Z0-9_.]/', '', $_POST['package_id'] ?? 'com.example.app');
    $pages     = json_decode($_POST['pages'], true);

    $build = sys_get_temp_dir() . '/apk_' . uniqid();
    mkdir($build, 0777, true);
    mkdir("$build/assets", 0777, true);
    mkdir("$build/res", 0777, true);

    foreach ($pages as $name => $html) {
        file_put_contents("$build/assets/$name.html", $html);
    }

    if (!empty($_FILES['icon']['tmp_name'])) {
        move_uploaded_file($_FILES['icon']['tmp_name'], "$build/res/icon.png");
    }

    file_put_contents(
        "$build/AndroidManifest.xml",
        "<manifest package=\"$packageId\">
          <application android:label=\"$appName\">
            <activity android:name=\"Main\" />
          </application>
        </manifest>"
    );

    $apk = "$build/$appName.apk";
    $zip = new ZipArchive();
    $zip->open($apk, ZipArchive::CREATE);
    foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($build)) as $f) {
        if ($f->isFile()) {
            $zip->addFile($f, substr($f, strlen($build) + 1));
        }
    }
    $zip->close();

    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"$appName.apk\"");
    readfile($apk);
    exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WYSIWYG → APK Studio</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<style>
:root {
  --bg:#0f172a; --panel:#1e293b; --accent:#22c55e; --dim:#94a3b8;
}
* { box-sizing:border-box; font-family:system-ui,sans-serif; }
body { margin:0; background:var(--bg); color:#fff; }

header {
  padding:14px 18px; background:#020617;
  display:flex; justify-content:space-between; align-items:center;
}

main {
  display:grid;
  grid-template-columns:260px 1fr 420px;
  height:calc(100vh - 56px);
}

.sidebar, .editor, .preview { padding:12px; overflow:auto; }
.sidebar { background:#020617; }
.editor { background:var(--panel); }
.preview { background:#020617; }

h3 { margin:8px 0; color:var(--dim); font-weight:500; }

.block {
  background:#334155; padding:10px; border-radius:10px;
  margin-bottom:8px; text-align:center; cursor:grab;
}

.toolbar { display:flex; gap:8px; margin-bottom:8px; }
.toolbar button {
  background:#334155; border:none; color:#fff;
  padding:6px 10px; border-radius:8px; cursor:pointer;
}

.tabs { display:flex; gap:6px; margin-bottom:6px; }
.tabs button {
  background:#1e293b; border:none; color:#fff;
  padding:6px 10px; border-radius:8px; cursor:pointer;
}

.canvas {
  background:#fff; color:#000; min-height:100%;
  border-radius:12px; padding:16px;
}

.canvas *:hover { outline:1px dashed var(--accent); }

textarea, input {
  width:100%; padding:8px; border-radius:8px; border:none;
  margin-bottom:8px;
}

iframe {
  width:100%; height:60%; border:none;
  border-radius:10px; background:#fff;
}

button.primary {
  width:100%; padding:10px; border:none;
  border-radius:10px; background:var(--accent);
  font-weight:600; cursor:pointer;
}
</style>
</head>

<body>

<header>
  <strong>🧩 Universal WYSIWYG APK Studio</strong>
  <div>
    <button onclick="undo()">↶</button>
    <button onclick="redo()">↷</button>
  </div>
</header>

<main>

<!-- COMPONENTS -->
<div class="sidebar">
  <h3>Components</h3>
  <div class="block" draggable="true" data-html="<h1>Heading</h1>">Heading</div>
  <div class="block" draggable="true" data-html="<p>Text block</p>">Text</div>
  https://picsum.photos/400/200">Image</div>
  <div class="block" draggable="true" data-html="<button>Button</button>">Button</div>
  https://example.com</iframe>">Web View</div>
  page2.htmlGo to Page</a>">Link Page</div>
</div>

<!-- EDITOR -->
<div class="editor">
  <div class="tabs" id="tabs"></div>

  <div class="toolbar">
    <button onclick="addPage()">+ Page</button>
    <button onclick="toggleCode()">Code</button>
  </div>

  <div id="canvas" class="canvas" contenteditable="true"></div>
  <textarea id="code" style="display:none;height:100%"></textarea>
</div>

<!-- PREVIEW / EXPORT -->
<div class="preview">
  <h3>Live Preview</h3>
  <iframe id="preview"></iframe>

  <form method="POST" enctype="multipart/form-data">
    <input name="app_name" placeholder="App Name" required>
    <input name="package_id" placeholder="com.example.app" required>
    <input type="file" name="icon" accept="image/*">
    <small>Icon: 512×512 PNG (auto‑resized)</small>

    <input type="hidden" name="pages" id="pages">
    <input type="hidden" name="export" value="1">

    <button class="primary" onclick="prepare()">Export APK</button>
  </form>
</div>

</main>

<script>
let pages = { index: "" };
let current = "index";
let history = [], future = [];
let codeMode = false;

const canvas = document.getElementById("canvas");
const code = document.getElementById("code");
const preview = document.getElementById("preview");
const tabs = document.getElementById("tabs");

function snapshot() {
  history.push(JSON.stringify(pages));
  future = [];
}

function undo() {
  if (!history.length) return;
  future.push(JSON.stringify(pages));
  pages = JSON.parse(history.pop());
  load(current);
}

function redo() {
  if (!future.length) return;
  history.push(JSON.stringify(pages));
  pages = JSON.parse(future.pop());
  load(current);
}

function sync() {
  pages[current] = codeMode ? code.value : canvas.innerHTML;
  preview.srcdoc = pages[current];
}

canvas.addEventListener("input", () => { snapshot(); sync(); });
code.addEventListener("input", () => { snapshot(); sync(); });

function toggleCode() {
  codeMode = !codeMode;
  canvas.style.display = codeMode ? "none" : "block";
  code.style.display = codeMode ? "block" : "none";
  code.value = canvas.innerHTML;
}

function addPage() {
  const name = prompt("Page name");
  if (!name || pages[name]) return;
  pages[name] = "";
  switchPage(name);
}

function switchPage(p) {
  pages[current] = canvas.innerHTML;
  current = p;
  load(p);
}

function load(p) {
  canvas.innerHTML = pages[p];
  code.value = pages[p];
  renderTabs();
  preview.srcdoc = pages[p];
}

function renderTabs() {
  tabs.innerHTML = "";
  Object.keys(pages).forEach(p => {
    const b = document.createElement("button");
    b.textContent = p;
    b.onclick = () => switchPage(p);
    tabs.appendChild(b);
  });
}

document.querySelectorAll(".block").forEach(b => {
  b.addEventListener("dragstart", e => {
    e.dataTransfer.setData("text/html", b.dataset.html);
  });
});

canvas.addEventListener("dragover", e => e.preventDefault());
canvas.addEventListener("drop", e => {
  e.preventDefault();
  snapshot();
  canvas.innerHTML += e.dataTransfer.getData("text/html");
  sync();
});

function prepare() {
  pages[current] = canvas.innerHTML;
  document.getElementById("pages").value = JSON.stringify(pages);
}

renderTabs();
sync();
</script>

</body>
</html>