import { EventBus } from '../core/EventBus.js';

/* ────────────────────────────────────────────────────────────────
   TutorialEngine — LEGENDARY interactive tutorial system
   
   Features:
   • Step-by-step tutorials with progress tracking
   • Multiple step types: text, code, highlight, interactive, quiz
   • Multi-language support via I18nManager
   • Overlay UI with arrows, spotlights, tooltips
   • Progress persistence (localStorage)
   • Tutorial packs as JSON
   • Code sandboxes with live validation
   • Kid-friendly mode with simplified language
──────────────────────────────────────────────────────────────── */
/* ── TutorialEngine ───────────────────────────────────────────── */
class TutorialEngine {
    constructor(i18n, persistProgress = true) {
        this.i18n = i18n;
        this.persistProgress = persistProgress;
        this.tutorials = new Map();
        this.progress = new Map();
        this.validators = new Map();
        this.activeTutorialId = null;
        this.storagePrefix = 'nice2dev_tutorial_';
        this.events = new EventBus();
        if (this.persistProgress) {
            this.loadAllProgress();
        }
    }
    /* ── Tutorial Registration ──────────────────────────────────── */
    /** Register a tutorial definition */
    registerTutorial(definition) {
        this.tutorials.set(definition.id, definition);
    }
    /** Register multiple tutorials at once */
    registerTutorials(definitions) {
        for (const def of definitions) {
            this.registerTutorial(def);
        }
    }
    /** Register a custom code validator */
    registerValidator(name, fn) {
        this.validators.set(name, fn);
    }
    /** Get all registered tutorials */
    getAllTutorials() {
        return Array.from(this.tutorials.values());
    }
    /** Get tutorials filtered by category */
    getTutorialsByCategory(category) {
        return this.getAllTutorials().filter(t => t.category === category);
    }
    /** Get tutorials filtered by difficulty */
    getTutorialsByDifficulty(difficulty) {
        return this.getAllTutorials().filter(t => t.difficulty === difficulty);
    }
    /** Get tutorials suitable for kids */
    getKidFriendlyTutorials() {
        return this.getAllTutorials().filter(t => t.kidFriendly === true);
    }
    /** Search tutorials by tag or title */
    searchTutorials(query) {
        const lowerQuery = query.toLowerCase();
        const locale = this.i18n.getLocale();
        return this.getAllTutorials().filter(t => {
            var _a, _b, _c, _d, _e;
            const title = ((_b = (_a = t.title[locale]) !== null && _a !== void 0 ? _a : t.title['en']) !== null && _b !== void 0 ? _b : '').toLowerCase();
            const desc = ((_d = (_c = t.description[locale]) !== null && _c !== void 0 ? _c : t.description['en']) !== null && _d !== void 0 ? _d : '').toLowerCase();
            const tagMatch = (_e = t.tags) === null || _e === void 0 ? void 0 : _e.some(tag => tag.toLowerCase().includes(lowerQuery));
            return title.includes(lowerQuery) || desc.includes(lowerQuery) || tagMatch;
        });
    }
    /* ── Tutorial Execution ─────────────────────────────────────── */
    /** Start a tutorial */
    startTutorial(tutorialId) {
        const tutorial = this.tutorials.get(tutorialId);
        if (!tutorial || tutorial.steps.length === 0)
            return null;
        // Check prerequisites
        if (tutorial.prerequisites) {
            for (const preReqId of tutorial.prerequisites) {
                const preReqProgress = this.progress.get(preReqId);
                if (!(preReqProgress === null || preReqProgress === void 0 ? void 0 : preReqProgress.completed)) {
                    return null; // Prerequisite not met
                }
            }
        }
        // Get or create progress
        let prog = this.progress.get(tutorialId);
        if (!prog || prog.completed) {
            prog = {
                tutorialId,
                currentStepIndex: 0,
                completedSteps: [],
                startedAt: Date.now(),
                lastAccessedAt: Date.now(),
                completed: false,
                quizScores: {},
                codeSubmissions: {},
            };
            this.progress.set(tutorialId, prog);
        }
        this.activeTutorialId = tutorialId;
        this.events.emit('tutorial:started', { tutorialId });
        const step = tutorial.steps[prog.currentStepIndex];
        this.events.emit('tutorial:step:entered', {
            tutorialId,
            stepId: step.id,
            stepIndex: prog.currentStepIndex,
        });
        this.saveProgress(tutorialId);
        return step;
    }
    /** Get the current step of the active tutorial */
    getCurrentStep() {
        var _a;
        if (!this.activeTutorialId)
            return null;
        const tutorial = this.tutorials.get(this.activeTutorialId);
        const prog = this.progress.get(this.activeTutorialId);
        if (!tutorial || !prog)
            return null;
        return (_a = tutorial.steps[prog.currentStepIndex]) !== null && _a !== void 0 ? _a : null;
    }
    /** Advance to the next step */
    nextStep() {
        if (!this.activeTutorialId)
            return null;
        const tutorial = this.tutorials.get(this.activeTutorialId);
        const prog = this.progress.get(this.activeTutorialId);
        if (!tutorial || !prog)
            return null;
        // Mark current step completed
        const currentStep = tutorial.steps[prog.currentStepIndex];
        if (currentStep && !prog.completedSteps.includes(currentStep.id)) {
            prog.completedSteps.push(currentStep.id);
            this.events.emit('tutorial:step:completed', {
                tutorialId: this.activeTutorialId,
                stepId: currentStep.id,
            });
        }
        // Advance
        prog.currentStepIndex++;
        prog.lastAccessedAt = Date.now();
        // Check if tutorial is completed
        if (prog.currentStepIndex >= tutorial.steps.length) {
            prog.completed = true;
            prog.completedAt = Date.now();
            this.events.emit('tutorial:completed', {
                tutorialId: this.activeTutorialId,
                durationMs: prog.completedAt - prog.startedAt,
            });
            this.saveProgress(this.activeTutorialId);
            this.activeTutorialId = null;
            return null;
        }
        const nextStep = tutorial.steps[prog.currentStepIndex];
        this.events.emit('tutorial:step:entered', {
            tutorialId: this.activeTutorialId,
            stepId: nextStep.id,
            stepIndex: prog.currentStepIndex,
        });
        this.saveProgress(this.activeTutorialId);
        return nextStep;
    }
    /** Go to a previous step */
    previousStep() {
        if (!this.activeTutorialId)
            return null;
        const tutorial = this.tutorials.get(this.activeTutorialId);
        const prog = this.progress.get(this.activeTutorialId);
        if (!tutorial || !prog || prog.currentStepIndex <= 0)
            return null;
        prog.currentStepIndex--;
        prog.lastAccessedAt = Date.now();
        const step = tutorial.steps[prog.currentStepIndex];
        this.events.emit('tutorial:step:entered', {
            tutorialId: this.activeTutorialId,
            stepId: step.id,
            stepIndex: prog.currentStepIndex,
        });
        this.saveProgress(this.activeTutorialId);
        return step;
    }
    /** Jump to a specific step by index */
    goToStep(index) {
        if (!this.activeTutorialId)
            return null;
        const tutorial = this.tutorials.get(this.activeTutorialId);
        const prog = this.progress.get(this.activeTutorialId);
        if (!tutorial || !prog)
            return null;
        if (index < 0 || index >= tutorial.steps.length)
            return null;
        prog.currentStepIndex = index;
        prog.lastAccessedAt = Date.now();
        const step = tutorial.steps[index];
        this.events.emit('tutorial:step:entered', {
            tutorialId: this.activeTutorialId,
            stepId: step.id,
            stepIndex: index,
        });
        this.saveProgress(this.activeTutorialId);
        return step;
    }
    /** Stop the current tutorial */
    stopTutorial() {
        if (this.activeTutorialId) {
            this.saveProgress(this.activeTutorialId);
            this.activeTutorialId = null;
        }
    }
    /* ── Step Interaction ───────────────────────────────────────── */
    /** Submit a quiz answer */
    submitQuizAnswer(answerId) {
        if (!this.activeTutorialId)
            return false;
        const step = this.getCurrentStep();
        const prog = this.progress.get(this.activeTutorialId);
        if (!step || !prog || step.type !== 'quiz')
            return false;
        const correct = answerId === step.quizCorrectId;
        prog.quizScores[step.id] = correct;
        this.events.emit('tutorial:quiz:answered', {
            tutorialId: this.activeTutorialId,
            stepId: step.id,
            correct,
        });
        this.saveProgress(this.activeTutorialId);
        return correct;
    }
    /** Submit code for validation */
    validateCode(code) {
        if (!this.activeTutorialId)
            return { valid: false, message: 'No active tutorial' };
        const step = this.getCurrentStep();
        const prog = this.progress.get(this.activeTutorialId);
        if (!step || !prog || step.type !== 'code')
            return { valid: false, message: 'Not a code step' };
        // Store submission
        prog.codeSubmissions[step.id] = code;
        const validation = step.codeValidation;
        if (!validation) {
            // No validation rules = always valid
            this.events.emit('tutorial:code:validated', {
                tutorialId: this.activeTutorialId,
                stepId: step.id,
                valid: true,
            });
            return { valid: true };
        }
        // Pattern match
        if (validation.pattern) {
            const regex = new RegExp(validation.pattern);
            if (!regex.test(code)) {
                this.events.emit('tutorial:code:validated', {
                    tutorialId: this.activeTutorialId,
                    stepId: step.id,
                    valid: false,
                });
                return { valid: false, message: 'Code does not match the expected pattern' };
            }
        }
        // Contains all
        if (validation.containsAll) {
            for (const s of validation.containsAll) {
                if (!code.includes(s)) {
                    this.events.emit('tutorial:code:validated', {
                        tutorialId: this.activeTutorialId,
                        stepId: step.id,
                        valid: false,
                    });
                    return { valid: false, message: `Missing required code: "${s}"` };
                }
            }
        }
        // Contains any
        if (validation.containsAny) {
            const found = validation.containsAny.some(s => code.includes(s));
            if (!found) {
                this.events.emit('tutorial:code:validated', {
                    tutorialId: this.activeTutorialId,
                    stepId: step.id,
                    valid: false,
                });
                return { valid: false, message: 'Code is missing a required element' };
            }
        }
        // Max lines
        if (validation.maxLines) {
            const lineCount = code.split('\n').length;
            if (lineCount > validation.maxLines) {
                this.events.emit('tutorial:code:validated', {
                    tutorialId: this.activeTutorialId,
                    stepId: step.id,
                    valid: false,
                });
                return { valid: false, message: `Code exceeds ${validation.maxLines} lines` };
            }
        }
        // Custom validator
        if (validation.customValidator) {
            const validatorFn = this.validators.get(validation.customValidator);
            if (validatorFn) {
                const result = validatorFn(code);
                this.events.emit('tutorial:code:validated', {
                    tutorialId: this.activeTutorialId,
                    stepId: step.id,
                    valid: result.valid,
                });
                return result;
            }
        }
        this.events.emit('tutorial:code:validated', {
            tutorialId: this.activeTutorialId,
            stepId: step.id,
            valid: true,
        });
        return { valid: true };
    }
    /** Request a hint for the current step */
    getHint() {
        var _a, _b;
        if (!this.activeTutorialId)
            return null;
        const step = this.getCurrentStep();
        if (!(step === null || step === void 0 ? void 0 : step.hint))
            return null;
        this.events.emit('tutorial:hint:shown', {
            tutorialId: this.activeTutorialId,
            stepId: step.id,
        });
        const locale = this.i18n.getLocale();
        return (_b = (_a = step.hint[locale]) !== null && _a !== void 0 ? _a : step.hint['en']) !== null && _b !== void 0 ? _b : null;
    }
    /** Get localized content for current step */
    getStepContent(step) {
        var _a, _b, _c, _d;
        const locale = this.i18n.getLocale();
        return {
            title: (_b = (_a = step.title[locale]) !== null && _a !== void 0 ? _a : step.title['en']) !== null && _b !== void 0 ? _b : step.id,
            content: (_d = (_c = step.content[locale]) !== null && _c !== void 0 ? _c : step.content['en']) !== null && _d !== void 0 ? _d : '',
        };
    }
    /* ── Progress Management ────────────────────────────────────── */
    /** Get progress for a tutorial */
    getProgress(tutorialId) {
        return this.progress.get(tutorialId);
    }
    /** Get progress percentage (0 to 1) */
    getProgressPercent(tutorialId) {
        const tutorial = this.tutorials.get(tutorialId);
        const prog = this.progress.get(tutorialId);
        if (!tutorial || !prog || tutorial.steps.length === 0)
            return 0;
        if (prog.completed)
            return 1;
        return prog.completedSteps.length / tutorial.steps.length;
    }
    /** Check if a tutorial is completed */
    isCompleted(tutorialId) {
        var _a;
        return ((_a = this.progress.get(tutorialId)) === null || _a === void 0 ? void 0 : _a.completed) === true;
    }
    /** Get quiz score summary for a completed tutorial */
    getQuizScore(tutorialId) {
        const prog = this.progress.get(tutorialId);
        if (!prog)
            return { correct: 0, total: 0, percentage: 0 };
        const entries = Object.values(prog.quizScores);
        const total = entries.length;
        const correct = entries.filter(Boolean).length;
        return {
            correct,
            total,
            percentage: total > 0 ? (correct / total) * 100 : 0,
        };
    }
    /** Get all tutorials with their completion status */
    getAllProgress() {
        return this.getAllTutorials().map(tutorial => ({
            tutorial,
            progress: this.progress.get(tutorial.id),
            percent: this.getProgressPercent(tutorial.id),
        }));
    }
    /** Reset progress for a tutorial */
    resetProgress(tutorialId) {
        this.progress.delete(tutorialId);
        if (this.persistProgress) {
            this.removeStoredProgress(tutorialId);
        }
    }
    /** Reset all progress */
    resetAllProgress() {
        const ids = Array.from(this.progress.keys());
        this.progress.clear();
        if (this.persistProgress) {
            for (const id of ids) {
                this.removeStoredProgress(id);
            }
        }
    }
    /* ── Persistence ────────────────────────────────────────────── */
    saveProgress(tutorialId) {
        if (!this.persistProgress)
            return;
        const prog = this.progress.get(tutorialId);
        if (!prog)
            return;
        try {
            if (typeof localStorage !== 'undefined') {
                localStorage.setItem(`${this.storagePrefix}${tutorialId}`, JSON.stringify(prog));
                this.events.emit('tutorial:progress:saved', { tutorialId });
            }
        }
        catch (_a) {
            // localStorage might not be available or quota exceeded
        }
    }
    loadAllProgress() {
        try {
            if (typeof localStorage === 'undefined')
                return;
            for (let i = 0; i < localStorage.length; i++) {
                const key = localStorage.key(i);
                if (!(key === null || key === void 0 ? void 0 : key.startsWith(this.storagePrefix)))
                    continue;
                const raw = localStorage.getItem(key);
                if (!raw)
                    continue;
                const parsed = JSON.parse(raw);
                if (isProgressData(parsed)) {
                    this.progress.set(parsed.tutorialId, parsed);
                }
            }
        }
        catch (_a) {
            // Ignore parse/access errors
        }
    }
    removeStoredProgress(tutorialId) {
        try {
            if (typeof localStorage !== 'undefined') {
                localStorage.removeItem(`${this.storagePrefix}${tutorialId}`);
            }
        }
        catch (_a) {
            // Ignore
        }
    }
    /* ── State ──────────────────────────────────────────────────── */
    getActiveTutorialId() {
        return this.activeTutorialId;
    }
    getActiveTutorial() {
        var _a;
        if (!this.activeTutorialId)
            return null;
        return (_a = this.tutorials.get(this.activeTutorialId)) !== null && _a !== void 0 ? _a : null;
    }
    getTotalSteps() {
        var _a;
        if (!this.activeTutorialId)
            return 0;
        const tutorial = this.tutorials.get(this.activeTutorialId);
        return (_a = tutorial === null || tutorial === void 0 ? void 0 : tutorial.steps.length) !== null && _a !== void 0 ? _a : 0;
    }
    getCurrentStepIndex() {
        var _a;
        if (!this.activeTutorialId)
            return -1;
        const prog = this.progress.get(this.activeTutorialId);
        return (_a = prog === null || prog === void 0 ? void 0 : prog.currentStepIndex) !== null && _a !== void 0 ? _a : -1;
    }
    dispose() {
        this.stopTutorial();
        this.tutorials.clear();
        this.progress.clear();
        this.validators.clear();
    }
}
/* ── Type guard for loaded progress ──────────────────────────── */
function isProgressData(v) {
    if (typeof v !== 'object' || v === null)
        return false;
    const obj = v;
    return (typeof obj.tutorialId === 'string' &&
        typeof obj.currentStepIndex === 'number' &&
        Array.isArray(obj.completedSteps) &&
        typeof obj.startedAt === 'number');
}
/* ── Built-in Tutorials ──────────────────────────────────────── */
/** Tutorial: First Game — Bouncing Ball */
const TUTORIAL_FIRST_GAME = {
    id: 'first-game-bouncing-ball',
    title: {
        en: 'Your First Game: Bouncing Ball',
        pl: 'Twoja pierwsza gra: Odbijająca się piłka',
        de: 'Dein erstes Spiel: Hüpfender Ball',
    },
    description: {
        en: 'Learn to create a simple bouncing ball game. Perfect for beginners!',
        pl: 'Naucz się tworzyć prostą grę z odbijającą się piłką. Idealne na początek!',
        de: 'Lerne, ein einfaches Hüpfball-Spiel zu erstellen. Perfekt für Anfänger!',
    },
    category: 'game-basics',
    difficulty: 'beginner',
    estimatedMinutes: 15,
    kidFriendly: true,
    ageRange: { min: 8, max: 99 },
    tags: ['ball', 'physics', 'beginner', 'first-game'],
    steps: [
        {
            id: 'welcome',
            type: 'text',
            title: {
                en: 'Welcome!',
                pl: 'Witaj!',
                de: 'Willkommen!',
            },
            content: {
                en: 'In this tutorial, you will create a bouncing ball game! 🎮\n\nYou will learn:\n• How to create entities\n• How to add physics\n• How to handle collisions\n\nLet\'s get started!',
                pl: 'W tym samouczku stworzysz grę z odbijającą się piłką! 🎮\n\nNauczysz się:\n• Jak tworzyć obiekty\n• Jak dodawać fizykę\n• Jak obsługiwać kolizje\n\nZaczynajmy!',
                de: 'In diesem Tutorial erstellst du ein Hüpfball-Spiel! 🎮\n\nDu lernst:\n• Wie man Entities erstellt\n• Wie man Physik hinzufügt\n• Wie man Kollisionen behandelt\n\nLos geht\'s!',
            },
            skippable: true,
            tooltipPosition: 'center',
        },
        {
            id: 'create-engine',
            type: 'code',
            title: {
                en: 'Create the Game Engine',
                pl: 'Utwórz silnik gry',
                de: 'Erstelle die Game-Engine',
            },
            content: {
                en: 'First, let\'s create a game engine instance and set up the canvas.\n\nType the code below to initialize your game:',
                pl: 'Najpierw utwórzmy instancję silnika gry i skonfigurujmy canvas.\n\nWpisz poniższy kod, aby zainicjować grę:',
                de: 'Zuerst erstellen wir eine Game-Engine-Instanz und richten das Canvas ein.\n\nGib den folgenden Code ein, um dein Spiel zu initialisieren:',
            },
            codeTemplate: '// Create a game engine\nconst engine = ',
            codeSolution: 'const engine = new Engine({\n  canvas: document.getElementById("game"),\n  width: 800,\n  height: 600,\n});',
            codeValidation: {
                containsAll: ['new Engine', 'canvas'],
            },
            hint: {
                en: 'Use: new Engine({ canvas: ..., width: 800, height: 600 })',
                pl: 'Użyj: new Engine({ canvas: ..., width: 800, height: 600 })',
                de: 'Verwende: new Engine({ canvas: ..., width: 800, height: 600 })',
            },
        },
        {
            id: 'create-ball',
            type: 'code',
            title: {
                en: 'Create the Ball',
                pl: 'Utwórz piłkę',
                de: 'Erstelle den Ball',
            },
            content: {
                en: 'Now let\'s create a ball entity with a transform and a circle shape!',
                pl: 'Teraz stwórzmy obiekt piłki z transformacją i kształtem koła!',
                de: 'Jetzt erstellen wir eine Ball-Entity mit Transform und Kreisform!',
            },
            codeTemplate: '// Create a ball entity\nconst ball = engine.world.createEntity();\n// Add components here...',
            codeSolution: 'const ball = engine.world.createEntity();\nengine.world.addComponent(ball, "Transform", { x: 400, y: 100 });\nengine.world.addComponent(ball, "Sprite", { shape: "circle", radius: 20, color: "red" });',
            codeValidation: {
                containsAll: ['createEntity', 'Transform', 'addComponent'],
            },
            hint: {
                en: 'Create an entity, then add Transform and Sprite components.',
                pl: 'Utwórz obiekt, a następnie dodaj komponenty Transform i Sprite.',
                de: 'Erstelle eine Entity und füge Transform- und Sprite-Komponenten hinzu.',
            },
        },
        {
            id: 'add-physics',
            type: 'code',
            title: {
                en: 'Add Physics!',
                pl: 'Dodaj fizykę!',
                de: 'Füge Physik hinzu!',
            },
            content: {
                en: 'Let\'s make the ball fall and bounce! Add a RigidBody and a Collider.',
                pl: 'Sprawmy, żeby piłka spadała i odbijała się! Dodaj RigidBody i Collider.',
                de: 'Lass den Ball fallen und abprallen! Füge einen RigidBody und einen Collider hinzu.',
            },
            codeTemplate: '// Add physics to the ball\n',
            codeSolution: 'engine.world.addComponent(ball, "RigidBody2D", { type: "dynamic", gravityScale: 1 });\nengine.world.addComponent(ball, "Collider2D", { shape: "circle", radius: 20, restitution: 0.8 });',
            codeValidation: {
                containsAll: ['RigidBody2D', 'Collider2D', 'restitution'],
            },
            hint: {
                en: 'RigidBody2D makes it move, Collider2D detects hits. Set restitution > 0 for bounce!',
                pl: 'RigidBody2D porusza obiekt, Collider2D wykrywa zderzenia. Ustaw restitution > 0 dla odbicia!',
                de: 'RigidBody2D bewegt es, Collider2D erkennt Treffer. Setze restitution > 0 für Abprallen!',
            },
        },
        {
            id: 'quiz-physics',
            type: 'quiz',
            title: {
                en: 'Quick Quiz! 🧠',
                pl: 'Szybki quiz! 🧠',
                de: 'Schnelles Quiz! 🧠',
            },
            content: {
                en: 'What does the "restitution" value control?',
                pl: 'Co kontroluje wartość "restitution"?',
                de: 'Was steuert der "restitution"-Wert?',
            },
            quizOptions: [
                { id: 'a', text: { en: 'The ball\'s color', pl: 'Kolor piłki', de: 'Die Farbe des Balls' } },
                { id: 'b', text: { en: 'How bouncy the ball is', pl: 'Jak bardzo piłka się odbija', de: 'Wie stark der Ball abprallt' } },
                { id: 'c', text: { en: 'The ball\'s speed', pl: 'Prędkość piłki', de: 'Die Geschwindigkeit des Balls' } },
                { id: 'd', text: { en: 'The ball\'s size', pl: 'Rozmiar piłki', de: 'Die Größe des Balls' } },
            ],
            quizCorrectId: 'b',
        },
        {
            id: 'create-floor',
            type: 'code',
            title: {
                en: 'Create the Floor',
                pl: 'Utwórz podłogę',
                de: 'Erstelle den Boden',
            },
            content: {
                en: 'The ball needs something to bounce off! Create a static floor at the bottom.',
                pl: 'Piłka potrzebuje czegoś, od czego się odbije! Utwórz statyczną podłogę na dole.',
                de: 'Der Ball braucht etwas zum Abprallen! Erstelle einen statischen Boden unten.',
            },
            codeTemplate: '// Create a floor\nconst floor = engine.world.createEntity();\n',
            codeSolution: 'const floor = engine.world.createEntity();\nengine.world.addComponent(floor, "Transform", { x: 400, y: 580 });\nengine.world.addComponent(floor, "Collider2D", { shape: "box", width: 800, height: 20 });\nengine.world.addComponent(floor, "RigidBody2D", { type: "static" });',
            codeValidation: {
                containsAll: ['createEntity', 'static', 'Collider2D'],
            },
            hint: {
                en: 'Use RigidBody2D type: "static" — the floor shouldn\'t move!',
                pl: 'Użyj RigidBody2D type: "static" — podłoga nie powinna się ruszać!',
                de: 'Verwende RigidBody2D type: "static" — der Boden soll sich nicht bewegen!',
            },
        },
        {
            id: 'start-game',
            type: 'code',
            title: {
                en: 'Start the Game! 🚀',
                pl: 'Uruchom grę! 🚀',
                de: 'Starte das Spiel! 🚀',
            },
            content: {
                en: 'Everything is ready! Start the game loop to see your bouncing ball in action!',
                pl: 'Wszystko gotowe! Uruchom pętlę gry, aby zobaczyć swoją odbijającą się piłkę w akcji!',
                de: 'Alles bereit! Starte die Game-Loop, um deinen hüpfenden Ball in Aktion zu sehen!',
            },
            codeTemplate: '// Start the game\n',
            codeSolution: 'engine.start();',
            codeValidation: {
                containsAll: ['engine.start'],
            },
        },
        {
            id: 'congratulations',
            type: 'text',
            title: {
                en: 'Congratulations! 🎉',
                pl: 'Gratulacje! 🎉',
                de: 'Herzlichen Glückwunsch! 🎉',
            },
            content: {
                en: 'You just created your first game with Nice2Dev Game Engine!\n\n🏆 You learned:\n• Creating entities\n• Adding components (Transform, Sprite, RigidBody2D, Collider2D)\n• Physics simulation with restitution\n• Starting the game loop\n\nNext up: Try the "Space Shooter" tutorial! 🚀',
                pl: 'Właśnie stworzyłeś swoją pierwszą grę z Nice2Dev Game Engine!\n\n🏆 Nauczyłeś się:\n• Tworzenia obiektów\n• Dodawania komponentów (Transform, Sprite, RigidBody2D, Collider2D)\n• Symulacji fizyki z restitution\n• Uruchamiania pętli gry\n\nNastępnie: Spróbuj samouczka "Kosmiczny Strzelec"! 🚀',
                de: 'Du hast gerade dein erstes Spiel mit Nice2Dev Game Engine erstellt!\n\n🏆 Du hast gelernt:\n• Entities erstellen\n• Komponenten hinzufügen (Transform, Sprite, RigidBody2D, Collider2D)\n• Physiksimulation mit Restitution\n• Game-Loop starten\n\nAls nächstes: Probiere das "Space Shooter"-Tutorial! 🚀',
            },
            tooltipPosition: 'center',
        },
    ],
};
/** Tutorial: Space Shooter */
const TUTORIAL_SPACE_SHOOTER = {
    id: 'space-shooter',
    title: {
        en: 'Space Shooter 🚀',
        pl: 'Kosmiczny Strzelec 🚀',
        de: 'Weltraum-Shooter 🚀',
    },
    description: {
        en: 'Build a classic space shooter! Learn input handling, spawning enemies, and scoring.',
        pl: 'Zbuduj klasyczną kosmiczną strzelankę! Naucz się obsługi sterowania, tworzenia wrogów i punktacji.',
        de: 'Baue einen klassischen Weltraum-Shooter! Lerne Eingabeverarbeitung, Gegner-Spawning und Punktestand.',
    },
    category: 'game-basics',
    difficulty: 'beginner',
    estimatedMinutes: 25,
    kidFriendly: true,
    ageRange: { min: 10, max: 99 },
    tags: ['shooter', 'space', 'input', 'spawning', 'scoring'],
    prerequisites: ['first-game-bouncing-ball'],
    steps: [
        {
            id: 'intro',
            type: 'text',
            title: { en: 'Space Shooter', pl: 'Kosmiczny Strzelec', de: 'Weltraum-Shooter' },
            content: {
                en: 'Welcome to the Space Shooter tutorial! 🚀\n\nYou will learn:\n• Keyboard input handling\n• Spawning entities dynamically\n• Collision-based scoring\n• Game over logic\n\nPrerequisite: "Your First Game: Bouncing Ball"',
                pl: 'Witaj w samouczku Kosmiczny Strzelec! 🚀\n\nNauczysz się:\n• Obsługi sterowania z klawiatury\n• Dynamicznego tworzenia obiektów\n• Punktacji na podstawie kolizji\n• Logiki końca gry\n\nWymagany: "Twoja pierwsza gra: Odbijająca się piłka"',
                de: 'Willkommen beim Weltraum-Shooter Tutorial! 🚀\n\nDu lernst:\n• Tastatureingabe-Verarbeitung\n• Dynamisches Entity-Spawning\n• Kollisionsbasiertes Scoring\n• Game-Over-Logik\n\nVoraussetzung: "Dein erstes Spiel: Hüpfender Ball"',
            },
            tooltipPosition: 'center',
        },
        {
            id: 'setup-scene',
            type: 'code',
            title: { en: 'Setup the Scene', pl: 'Przygotuj scenę', de: 'Szene einrichten' },
            content: {
                en: 'Create the engine and a spaceship entity. The ship should be at the bottom center of the screen.',
                pl: 'Utwórz silnik i obiekt statku kosmicznego. Statek powinien być na dole, pośrodku ekranu.',
                de: 'Erstelle die Engine und eine Raumschiff-Entity. Das Schiff soll unten in der Mitte des Bildschirms sein.',
            },
            codeTemplate: '// Setup engine and player ship\nconst engine = new Engine({ canvas: document.getElementById("game"), width: 800, height: 600 });\n\n// Create player ship\n',
            codeSolution: 'const ship = engine.world.createEntity();\nengine.world.addComponent(ship, "Transform", { x: 400, y: 550 });\nengine.world.addComponent(ship, "Sprite", { shape: "triangle", width: 30, height: 40, color: "cyan" });',
            codeValidation: { containsAll: ['createEntity', 'Transform', 'Sprite'] },
        },
        {
            id: 'add-input',
            type: 'code',
            title: { en: 'Add Controls', pl: 'Dodaj sterowanie', de: 'Steuerung hinzufügen' },
            content: {
                en: 'Let\'s make the ship move with arrow keys! Create a system that reads keyboard input.',
                pl: 'Sprawmy, żeby statek poruszał się strzałkami! Stwórz system odczytujący klawiaturę.',
                de: 'Lass das Schiff mit Pfeiltasten bewegen! Erstelle ein System, das Tastatureingaben liest.',
            },
            codeTemplate: '// Movement system\nengine.world.addSystem("ShipMovement", (world) => {\n  // Your code here\n});\n',
            codeSolution: 'engine.world.addSystem("ShipMovement", (world) => {\n  const input = engine.input;\n  const transform = world.getComponent(ship, "Transform");\n  const speed = 5;\n  if (input.isKeyDown("ArrowLeft")) transform.x -= speed;\n  if (input.isKeyDown("ArrowRight")) transform.x += speed;\n});',
            codeValidation: { containsAll: ['isKeyDown', 'ArrowLeft', 'ArrowRight'] },
            hint: {
                en: 'Use engine.input.isKeyDown("ArrowLeft/ArrowRight") to check keys.',
                pl: 'Użyj engine.input.isKeyDown("ArrowLeft/ArrowRight") do sprawdzenia klawiszy.',
                de: 'Verwende engine.input.isKeyDown("ArrowLeft/ArrowRight") um Tasten zu prüfen.',
            },
        },
        {
            id: 'quiz-input',
            type: 'quiz',
            title: { en: 'Input Quiz 🧠', pl: 'Quiz o sterowaniu 🧠', de: 'Eingabe-Quiz 🧠' },
            content: {
                en: 'What is the difference between isKeyDown and isKeyPressed?',
                pl: 'Jaka jest różnica między isKeyDown i isKeyPressed?',
                de: 'Was ist der Unterschied zwischen isKeyDown und isKeyPressed?',
            },
            quizOptions: [
                { id: 'a', text: { en: 'They are the same thing', pl: 'To to samo', de: 'Sie sind dasselbe' } },
                { id: 'b', text: { en: 'isKeyDown is continuous, isKeyPressed is single-frame', pl: 'isKeyDown jest ciągły, isKeyPressed jednoklatkowo', de: 'isKeyDown ist kontinuierlich, isKeyPressed einmalig' } },
                { id: 'c', text: { en: 'isKeyDown works only with arrows', pl: 'isKeyDown działa tylko ze strzałkami', de: 'isKeyDown funktioniert nur mit Pfeiltasten' } },
            ],
            quizCorrectId: 'b',
        },
        {
            id: 'shooting',
            type: 'code',
            title: { en: 'Shoot Bullets! 🔫', pl: 'Strzelaj pociskami! 🔫', de: 'Schieße Kugeln! 🔫' },
            content: {
                en: 'Add shooting! When Space is pressed, create a bullet entity that moves upward.',
                pl: 'Dodaj strzelanie! Po naciśnięciu Spacji utwórz pocisk, który leci w górę.',
                de: 'Füge Schießen hinzu! Bei Leertaste einen Kugel-Entity erstellen, der nach oben fliegt.',
            },
            codeTemplate: '// Shooting system\nengine.world.addSystem("Shooting", (world) => {\n  const input = engine.input;\n  // Your shooting code here\n});\n',
            codeSolution: 'if (input.isKeyPressed("Space")) {\n  const bullet = world.createEntity();\n  const shipPos = world.getComponent(ship, "Transform");\n  world.addComponent(bullet, "Transform", { x: shipPos.x, y: shipPos.y - 20 });\n  world.addComponent(bullet, "Velocity", { x: 0, y: -10 });\n  world.addComponent(bullet, "Sprite", { shape: "rect", width: 4, height: 10, color: "yellow" });\n}',
            codeValidation: { containsAll: ['isKeyPressed', 'Space', 'createEntity', 'bullet'] },
            hint: {
                en: 'Use isKeyPressed (not isKeyDown!) for single-shot per press.',
                pl: 'Użyj isKeyPressed (nie isKeyDown!) dla jednego strzału na naciśnięcie.',
                de: 'Verwende isKeyPressed (nicht isKeyDown!) für einen Schuss pro Tastendruck.',
            },
        },
        {
            id: 'checkpoint-halfway',
            type: 'checkpoint',
            title: { en: 'Halfway There! 🎯', pl: 'Połowa drogi! 🎯', de: 'Halb geschafft! 🎯' },
            content: {
                en: 'Great progress! You have a moving ship that can shoot. Let\'s add enemies next!',
                pl: 'Świetne postępy! Masz poruszający się statek, który potrafi strzelać. Dodajmy teraz wrogów!',
                de: 'Toller Fortschritt! Du hast ein bewegliches Schiff, das schießen kann. Fügen wir als nächstes Gegner hinzu!',
            },
        },
        {
            id: 'complete',
            type: 'text',
            title: { en: 'Mission Complete! 🏆', pl: 'Misja zakończona! 🏆', de: 'Mission abgeschlossen! 🏆' },
            content: {
                en: 'You built a Space Shooter! 🚀\n\nSkills mastered:\n• Input handling (keyboard)\n• Dynamic entity spawning\n• Entity removal\n• Systems architecture\n\nChallenge: Add a scoring system and display it on screen!',
                pl: 'Zbudowałeś Kosmicznego Strzelca! 🚀\n\nOpanowane umiejętności:\n• Obsługa sterowania (klawiatura)\n• Dynamiczne tworzenie obiektów\n• Usuwanie obiektów\n• Architektura systemów\n\nWyzwanie: Dodaj system punktacji i wyświetl go na ekranie!',
                de: 'Du hast einen Weltraum-Shooter gebaut! 🚀\n\nGelernte Fähigkeiten:\n• Eingabeverarbeitung (Tastatur)\n• Dynamisches Entity-Spawning\n• Entity-Entfernung\n• System-Architektur\n\nHerausforderung: Füge ein Punktesystem hinzu und zeige es auf dem Bildschirm an!',
            },
            tooltipPosition: 'center',
        },
    ],
};
/** Tutorial: NiceDataGrid basics (for nice2dev-ui) */
const TUTORIAL_DATAGRID_BASICS = {
    id: 'ui-datagrid-basics',
    title: {
        en: 'NiceDataGrid: Master the Grid',
        pl: 'NiceDataGrid: Opanuj siatkę',
        de: 'NiceDataGrid: Das Grid meistern',
    },
    description: {
        en: 'Learn to use NiceDataGrid for sorting, filtering, grouping, and editing data.',
        pl: 'Naucz się używać NiceDataGrid do sortowania, filtrowania, grupowania i edycji danych.',
        de: 'Lerne NiceDataGrid für Sortieren, Filtern, Gruppieren und Bearbeiten von Daten.',
    },
    category: 'ui-controls',
    difficulty: 'beginner',
    estimatedMinutes: 20,
    kidFriendly: false,
    tags: ['grid', 'data', 'filtering', 'sorting', 'nice2dev-ui'],
    steps: [
        {
            id: 'intro',
            type: 'text',
            title: { en: 'Welcome to NiceDataGrid', pl: 'Witaj w NiceDataGrid', de: 'Willkommen bei NiceDataGrid' },
            content: {
                en: 'NiceDataGrid is a powerful data table component.\n\nYou will learn:\n• Creating a basic grid\n• Adding columns\n• Sorting & filtering\n• Grouping data\n• Cell editing',
                pl: 'NiceDataGrid to potężny komponent tabeli danych.\n\nNauczysz się:\n• Tworzenia podstawowej siatki\n• Dodawania kolumn\n• Sortowania i filtrowania\n• Grupowania danych\n• Edycji komórek',
                de: 'NiceDataGrid ist eine leistungsstarke Datentabellen-Komponente.\n\nDu lernst:\n• Ein einfaches Grid erstellen\n• Spalten hinzufügen\n• Sortieren & Filtern\n• Daten gruppieren\n• Zellenbearbeitung',
            },
        },
        {
            id: 'basic-grid',
            type: 'code',
            title: { en: 'Create a Grid', pl: 'Utwórz siatkę', de: 'Grid erstellen' },
            content: {
                en: 'Create a basic NiceDataGrid with a data source and columns.',
                pl: 'Utwórz podstawową NiceDataGrid ze źródłem danych i kolumnami.',
                de: 'Erstelle ein einfaches NiceDataGrid mit Datenquelle und Spalten.',
            },
            codeTemplate: 'import { NiceDataGrid } from "@nice2dev/ui";\n\n// Create your grid\n',
            codeSolution: '<NiceDataGrid\n  dataSource={employees}\n  columns={[\n    { dataField: "name", caption: "Name" },\n    { dataField: "department", caption: "Department" },\n    { dataField: "salary", caption: "Salary", dataType: "number" },\n  ]}\n  sorting={{ enabled: true }}\n  filtering={{ enabled: true }}\n/>',
            codeValidation: { containsAll: ['NiceDataGrid', 'dataSource', 'columns'] },
        },
        {
            id: 'filtering',
            type: 'code',
            title: { en: 'Add Filtering', pl: 'Dodaj filtrowanie', de: 'Filter hinzufügen' },
            content: {
                en: 'Enable header filter and filter row for your grid.',
                pl: 'Włącz filtr nagłówka i wiersz filtrowania w siatce.',
                de: 'Aktiviere Header-Filter und Filter-Zeile für dein Grid.',
            },
            codeTemplate: '// Add filtering props to your grid\n',
            codeSolution: '<NiceDataGrid\n  dataSource={employees}\n  columns={columns}\n  filtering={{ enabled: true, filterRow: true, headerFilter: true }}\n/>',
            codeValidation: { containsAll: ['filtering', 'enabled', 'true'] },
        },
        {
            id: 'quiz-filtering',
            type: 'quiz',
            title: { en: 'Filtering Quiz 🧠', pl: 'Quiz o filtrowaniu 🧠', de: 'Filter-Quiz 🧠' },
            content: {
                en: 'What is the difference between headerFilter and filterRow?',
                pl: 'Jaka jest różnica między headerFilter a filterRow?',
                de: 'Was ist der Unterschied zwischen headerFilter und filterRow?',
            },
            quizOptions: [
                { id: 'a', text: { en: 'headerFilter shows a dropdown, filterRow shows a text input', pl: 'headerFilter pokazuje dropdown, filterRow pokazuje pole tekstowe', de: 'headerFilter zeigt Dropdown, filterRow zeigt Texteingabe' } },
                { id: 'b', text: { en: 'They are the same', pl: 'Są identyczne', de: 'Sie sind gleich' } },
                { id: 'c', text: { en: 'filterRow is faster', pl: 'filterRow jest szybszy', de: 'filterRow ist schneller' } },
            ],
            quizCorrectId: 'a',
        },
        {
            id: 'complete',
            type: 'text',
            title: { en: 'Grid Master! 🏆', pl: 'Mistrz Siatki! 🏆', de: 'Grid-Meister! 🏆' },
            content: {
                en: 'You now know the basics of NiceDataGrid!\n\n🏆 Skills:\n• Data binding\n• Column configuration\n• Sorting & filtering\n\nNext: Try grouping, editing, and custom cell templates!',
                pl: 'Znasz już podstawy NiceDataGrid!\n\n🏆 Umiejętności:\n• Wiązanie danych\n• Konfiguracja kolumn\n• Sortowanie i filtrowanie\n\nDalej: Spróbuj grupowania, edycji i własnych szablonów komórek!',
                de: 'Du kennst jetzt die Grundlagen von NiceDataGrid!\n\n🏆 Fähigkeiten:\n• Datenbindung\n• Spaltenkonfiguration\n• Sortieren & Filtern\n\nWeiter: Probiere Gruppieren, Bearbeiten und benutzerdefinierte Zellenvorlagen!',
            },
        },
    ],
};
/** Get all built-in tutorials */
function getBuiltInTutorials() {
    return [
        TUTORIAL_FIRST_GAME,
        TUTORIAL_SPACE_SHOOTER,
        TUTORIAL_DATAGRID_BASICS,
    ];
}

export { TUTORIAL_DATAGRID_BASICS, TUTORIAL_FIRST_GAME, TUTORIAL_SPACE_SHOOTER, TutorialEngine, getBuiltInTutorials };
//# sourceMappingURL=TutorialEngine.js.map
