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

/* ────────────────────────────────────────────────────────────────
   Tutorial Overlay UI — LEGENDARY L4
   
   Provides DOM-based overlay components for the tutorial system:
   • Spotlight mask (highlight a target element)
   • Tooltip with arrow (positioned relative to target)
   • Progress bar (current step / total)
   • Navigation buttons (next, back, skip)
   • Quiz renderer
   
   Designed for use in HTML/DOM environments.
──────────────────────────────────────────────────────────────── */
const DEFAULT_OVERLAY_CONFIG = {
    zIndex: 10000,
    spotlightPadding: 8,
    spotlightBorderRadius: 8,
    maskOpacity: 0.65,
    animate: true,
    animationDuration: 300,
    theme: 'dark',
    classPrefix: 'n2d-tutorial',
    closeOnOutsideClick: false,
    showProgress: true,
    showNavigation: true,
    locale: 'en',
};
/* Button label translations. */
const BUTTON_LABELS = {
    next: { en: 'Next', pl: 'Dalej', de: 'Weiter', es: 'Siguiente', fr: 'Suivant', ja: '次へ', ko: '다음', 'zh-CN': '下一步' },
    back: { en: 'Back', pl: 'Wstecz', de: 'Zurück', es: 'Atrás', fr: 'Retour', ja: '戻る', ko: '뒤로', 'zh-CN': '返回' },
    skip: { en: 'Skip', pl: 'Pomiń', de: 'Überspringen', es: 'Saltar', fr: 'Passer', ja: 'スキップ', ko: '건너뛰기', 'zh-CN': '跳过' },
    close: { en: 'Close', pl: 'Zamknij', de: 'Schließen', es: 'Cerrar', fr: 'Fermer', ja: '閉じる', ko: '닫기', 'zh-CN': '关闭' },
    showHint: { en: 'Show Hint', pl: 'Pokaż podpowiedź', de: 'Hinweis zeigen', es: 'Mostrar pista', fr: 'Indice', ja: 'ヒント', ko: '힌트 보기', 'zh-CN': '提示' },
    submit: { en: 'Submit', pl: 'Zatwierdź', de: 'Absenden', es: 'Enviar', fr: 'Envoyer', ja: '送信', ko: '제출', 'zh-CN': '提交' },
};
/* ══════════════════════════════════════════════════════════════
   CSS Stylesheet (injected once)
   ══════════════════════════════════════════════════════════════ */
function generateStyles(cfg) {
    const p = cfg.classPrefix;
    const isDark = cfg.theme === 'dark';
    const bg = isDark ? '#1e1e2e' : '#ffffff';
    const fg = isDark ? '#e0e0e0' : '#1e1e2e';
    const accent = '#4fc3f7';
    const dur = `${cfg.animationDuration}ms`;
    return `
.${p}-mask {
  position: fixed;
  inset: 0;
  z-index: ${cfg.zIndex};
  pointer-events: none;
}
.${p}-mask-bg {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,${cfg.maskOpacity});
  z-index: ${cfg.zIndex};
  pointer-events: auto;
  transition: opacity ${dur} ease;
}
.${p}-spotlight {
  position: fixed;
  box-shadow: 0 0 0 9999px rgba(0,0,0,${cfg.maskOpacity});
  border-radius: ${cfg.spotlightBorderRadius}px;
  z-index: ${cfg.zIndex + 1};
  pointer-events: none;
  transition: all ${dur} ease;
}
.${p}-tooltip {
  position: fixed;
  z-index: ${cfg.zIndex + 2};
  background: ${bg};
  color: ${fg};
  border-radius: 12px;
  padding: 20px;
  max-width: 420px;
  min-width: 260px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.3);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  transition: all ${dur} ease;
}
.${p}-tooltip-title {
  font-size: 16px;
  font-weight: 700;
  margin-bottom: 8px;
  color: ${accent};
}
.${p}-tooltip-content {
  margin-bottom: 16px;
}
.${p}-tooltip-content code {
  background: ${isDark ? '#2d2d44' : '#f0f0f0'};
  padding: 2px 6px;
  border-radius: 4px;
  font-family: 'Fira Code', 'Cascadia Code', monospace;
  font-size: 13px;
}
.${p}-arrow {
  position: absolute;
  width: 12px;
  height: 12px;
  background: ${bg};
  transform: rotate(45deg);
}
.${p}-arrow-top { top: -6px; left: 50%; margin-left: -6px; }
.${p}-arrow-bottom { bottom: -6px; left: 50%; margin-left: -6px; }
.${p}-arrow-left { left: -6px; top: 50%; margin-top: -6px; }
.${p}-arrow-right { right: -6px; top: 50%; margin-top: -6px; }
.${p}-progress {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}
.${p}-progress-bar {
  flex: 1;
  height: 4px;
  background: ${isDark ? '#333' : '#ddd'};
  border-radius: 2px;
  overflow: hidden;
}
.${p}-progress-fill {
  height: 100%;
  background: ${accent};
  border-radius: 2px;
  transition: width ${dur} ease;
}
.${p}-progress-text {
  font-size: 12px;
  color: ${isDark ? '#888' : '#999'};
  white-space: nowrap;
}
.${p}-nav {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  margin-top: 12px;
}
.${p}-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  transition: background ${dur} ease;
}
.${p}-btn-primary {
  background: ${accent};
  color: #000;
}
.${p}-btn-primary:hover { background: #29b6f6; }
.${p}-btn-secondary {
  background: ${isDark ? '#333' : '#eee'};
  color: ${fg};
}
.${p}-btn-secondary:hover { background: ${isDark ? '#444' : '#ddd'}; }
.${p}-btn-skip {
  background: transparent;
  color: ${isDark ? '#888' : '#999'};
  text-decoration: underline;
}
.${p}-quiz-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}
.${p}-quiz-option {
  padding: 10px 14px;
  border: 2px solid ${isDark ? '#444' : '#ccc'};
  border-radius: 8px;
  cursor: pointer;
  transition: all 200ms ease;
  background: transparent;
  color: ${fg};
  text-align: left;
  font-size: 14px;
}
.${p}-quiz-option:hover {
  border-color: ${accent};
  background: ${isDark ? 'rgba(79,195,247,0.1)' : 'rgba(79,195,247,0.05)'};
}
.${p}-quiz-option.selected {
  border-color: ${accent};
  background: ${isDark ? 'rgba(79,195,247,0.2)' : 'rgba(79,195,247,0.1)'};
}
.${p}-quiz-option.correct {
  border-color: #4caf50;
  background: rgba(76,175,80,0.15);
}
.${p}-quiz-option.incorrect {
  border-color: #f44336;
  background: rgba(244,67,54,0.1);
}
.${p}-hint {
  margin-top: 8px;
  padding: 10px;
  border-radius: 6px;
  background: ${isDark ? '#2d2d44' : '#fff8e1'};
  border-left: 3px solid #ffc107;
  font-size: 13px;
}
.${p}-code-block {
  background: ${isDark ? '#1a1a2e' : '#f5f5f5'};
  border-radius: 8px;
  padding: 12px;
  margin: 8px 0;
  font-family: 'Fira Code', 'Cascadia Code', monospace;
  font-size: 13px;
  white-space: pre-wrap;
  overflow-x: auto;
  max-height: 200px;
  overflow-y: auto;
}
`;
}
/* ══════════════════════════════════════════════════════════════
   TutorialOverlay — Main overlay controller
   ══════════════════════════════════════════════════════════════ */
class TutorialOverlay {
    constructor(config) {
        this.events = new EventBus();
        this.container = null;
        this.styleEl = null;
        this.maskEl = null;
        this.spotlightEl = null;
        this.tooltipEl = null;
        this.active = false;
        this.currentTutorial = null;
        this.currentStepIndex = 0;
        this.selectedQuizAnswer = null;
        this.hintVisible = false;
        this.config = { ...DEFAULT_OVERLAY_CONFIG, ...config };
    }
    /** Whether the overlay is currently showing. */
    get isActive() { return this.active; }
    /** Current step index. */
    get stepIndex() { return this.currentStepIndex; }
    /** Total steps in current tutorial. */
    get totalSteps() { var _a, _b; return (_b = (_a = this.currentTutorial) === null || _a === void 0 ? void 0 : _a.steps.length) !== null && _b !== void 0 ? _b : 0; }
    /** Show the overlay for a tutorial at a given step. */
    show(tutorial, stepIndex = 0) {
        this.currentTutorial = tutorial;
        this.currentStepIndex = stepIndex;
        this.active = true;
        this.selectedQuizAnswer = null;
        this.hintVisible = false;
        this.ensureDOM();
        this.renderStep();
        this.events.emit('overlay:show', { tutorialId: tutorial.id, stepIndex });
    }
    /** Hide the overlay and clean up. */
    hide() {
        this.active = false;
        this.currentTutorial = null;
        this.currentStepIndex = 0;
        this.removeDOM();
        this.events.emit('overlay:hide', {});
    }
    /** Go to a specific step. */
    goToStep(index) {
        if (!this.currentTutorial)
            return;
        if (index < 0 || index >= this.currentTutorial.steps.length)
            return;
        this.currentStepIndex = index;
        this.selectedQuizAnswer = null;
        this.hintVisible = false;
        this.renderStep();
        this.events.emit('overlay:step', { stepIndex: index });
    }
    /** Advance to next step. */
    next() { this.goToStep(this.currentStepIndex + 1); }
    /** Go to previous step. */
    back() { this.goToStep(this.currentStepIndex - 1); }
    /** Update the locale for button labels. */
    setLocale(locale) {
        this.config.locale = locale;
        if (this.active)
            this.renderStep();
    }
    /* ── DOM Management ─────────────────────────────────────── */
    ensureDOM() {
        if (this.container)
            return;
        if (typeof document === 'undefined')
            return;
        // Inject styles once
        this.styleEl = document.createElement('style');
        this.styleEl.textContent = generateStyles(this.config);
        document.head.appendChild(this.styleEl);
        const p = this.config.classPrefix;
        // Mask background
        this.maskEl = document.createElement('div');
        this.maskEl.className = `${p}-mask-bg`;
        if (this.config.closeOnOutsideClick) {
            this.maskEl.addEventListener('click', () => {
                this.events.emit('overlay:action', { action: 'close' });
                this.hide();
            });
        }
        document.body.appendChild(this.maskEl);
        // Spotlight
        this.spotlightEl = document.createElement('div');
        this.spotlightEl.className = `${p}-spotlight`;
        document.body.appendChild(this.spotlightEl);
        // Tooltip container
        this.tooltipEl = document.createElement('div');
        this.tooltipEl.className = `${p}-tooltip`;
        document.body.appendChild(this.tooltipEl);
        this.container = this.maskEl; // just a flag
    }
    removeDOM() {
        if (this.styleEl) {
            this.styleEl.remove();
            this.styleEl = null;
        }
        if (this.maskEl) {
            this.maskEl.remove();
            this.maskEl = null;
        }
        if (this.spotlightEl) {
            this.spotlightEl.remove();
            this.spotlightEl = null;
        }
        if (this.tooltipEl) {
            this.tooltipEl.remove();
            this.tooltipEl = null;
        }
        this.container = null;
    }
    /* ── Rendering ──────────────────────────────────────────── */
    renderStep() {
        var _a, _b, _c, _d, _e, _f, _g;
        if (!this.currentTutorial || !this.tooltipEl || !this.spotlightEl || !this.maskEl)
            return;
        const step = this.currentTutorial.steps[this.currentStepIndex];
        if (!step)
            return;
        const locale = this.config.locale;
        const p = this.config.classPrefix;
        const title = (_b = (_a = step.title[locale]) !== null && _a !== void 0 ? _a : step.title['en']) !== null && _b !== void 0 ? _b : '';
        const content = (_d = (_c = step.content[locale]) !== null && _c !== void 0 ? _c : step.content['en']) !== null && _d !== void 0 ? _d : '';
        // Position spotlight on highlight target
        if (step.highlightTarget) {
            const target = document.querySelector(step.highlightTarget);
            if (target) {
                const rect = target.getBoundingClientRect();
                const pad = this.config.spotlightPadding;
                this.spotlightEl.style.display = 'block';
                this.spotlightEl.style.top = `${rect.top - pad}px`;
                this.spotlightEl.style.left = `${rect.left - pad}px`;
                this.spotlightEl.style.width = `${rect.width + pad * 2}px`;
                this.spotlightEl.style.height = `${rect.height + pad * 2}px`;
            }
            else {
                this.spotlightEl.style.display = 'none';
            }
        }
        else {
            this.spotlightEl.style.display = 'none';
        }
        // Build tooltip HTML
        let html = '';
        // Progress bar
        if (this.config.showProgress) {
            const pct = ((this.currentStepIndex + 1) / this.currentTutorial.steps.length) * 100;
            html += `<div class="${p}-progress">`;
            html += `<div class="${p}-progress-bar"><div class="${p}-progress-fill" style="width:${pct}%"></div></div>`;
            html += `<span class="${p}-progress-text">${this.currentStepIndex + 1} / ${this.currentTutorial.steps.length}</span>`;
            html += `</div>`;
        }
        // Title
        html += `<div class="${p}-tooltip-title">${this.escapeHtml(title)}</div>`;
        // Content
        html += `<div class="${p}-tooltip-content">${this.renderContent(content)}</div>`;
        // Code block (for code steps)
        if (step.type === 'code' && step.codeTemplate) {
            html += `<div class="${p}-code-block">${this.escapeHtml(step.codeTemplate)}</div>`;
        }
        // Quiz options
        if (step.type === 'quiz' && step.quizOptions) {
            html += this.renderQuizOptions(step.quizOptions, (_e = step.quizCorrectId) !== null && _e !== void 0 ? _e : '', locale);
        }
        // Hint
        if (step.hint) {
            const hintText = (_g = (_f = step.hint[locale]) !== null && _f !== void 0 ? _f : step.hint['en']) !== null && _g !== void 0 ? _g : '';
            if (hintText) {
                if (this.hintVisible) {
                    html += `<div class="${p}-hint">${this.escapeHtml(hintText)}</div>`;
                }
                else {
                    html += `<button class="${p}-btn ${p}-btn-secondary" data-action="hint">${this.label('showHint')}</button>`;
                }
            }
        }
        // Navigation
        if (this.config.showNavigation) {
            html += `<div class="${p}-nav">`;
            if (step.skippable) {
                html += `<button class="${p}-btn ${p}-btn-skip" data-action="skip">${this.label('skip')}</button>`;
            }
            if (this.currentStepIndex > 0) {
                html += `<button class="${p}-btn ${p}-btn-secondary" data-action="back">${this.label('back')}</button>`;
            }
            if (step.type === 'quiz') {
                html += `<button class="${p}-btn ${p}-btn-primary" data-action="submit">${this.label('submit')}</button>`;
            }
            else {
                html += `<button class="${p}-btn ${p}-btn-primary" data-action="next">${this.label('next')}</button>`;
            }
            html += `</div>`;
        }
        this.tooltipEl.innerHTML = html;
        // Position tooltip
        this.positionTooltip(step);
        // Bind events
        this.bindTooltipEvents(step);
    }
    renderContent(content) {
        // Convert backtick-wrapped code to <code> tags
        return this.escapeHtml(content).replace(/`([^`]+)`/g, '<code>$1</code>');
    }
    renderQuizOptions(options, correctId, locale) {
        var _a, _b, _c;
        const p = this.config.classPrefix;
        let html = `<div class="${p}-quiz-options">`;
        for (const opt of options) {
            let text;
            if (typeof opt.text === 'string') {
                text = opt.text;
            }
            else {
                text = (_b = (_a = opt.text[locale]) !== null && _a !== void 0 ? _a : opt.text['en']) !== null && _b !== void 0 ? _b : '???';
            }
            const optId = (_c = opt.id) !== null && _c !== void 0 ? _c : String(opt.text);
            let cls = `${p}-quiz-option`;
            if (this.selectedQuizAnswer === optId) {
                cls += ' selected';
                if (this.selectedQuizAnswer === correctId)
                    cls += ' correct';
                else
                    cls += ' incorrect';
            }
            html += `<button class="${cls}" data-quiz-id="${this.escapeHtml(optId)}">${this.escapeHtml(text)}</button>`;
        }
        html += `</div>`;
        return html;
    }
    positionTooltip(step) {
        var _a;
        if (!this.tooltipEl)
            return;
        const preferred = (_a = step.tooltipPosition) !== null && _a !== void 0 ? _a : 'bottom';
        // If there's a spotlight target, position relative to it
        if (step.highlightTarget) {
            const target = document.querySelector(step.highlightTarget);
            if (target) {
                const rect = target.getBoundingClientRect();
                const pos = this.calculatePosition(rect, preferred);
                this.tooltipEl.style.top = `${pos.top}px`;
                this.tooltipEl.style.left = `${pos.left}px`;
                // Add arrow
                const p = this.config.classPrefix;
                const existingArrow = this.tooltipEl.querySelector(`.${p}-arrow`);
                if (existingArrow)
                    existingArrow.remove();
                const arrowEl = document.createElement('div');
                arrowEl.className = `${p}-arrow ${p}-arrow-${pos.arrowDirection}`;
                this.tooltipEl.appendChild(arrowEl);
                return;
            }
        }
        // Center on screen
        this.tooltipEl.style.top = '50%';
        this.tooltipEl.style.left = '50%';
        this.tooltipEl.style.transform = 'translate(-50%, -50%)';
    }
    calculatePosition(targetRect, preferred) {
        const gap = 16;
        const tooltipWidth = 380;
        const tooltipHeight = 200;
        const vw = window.innerWidth;
        const vh = window.innerHeight;
        switch (preferred) {
            case 'bottom': {
                const top = targetRect.bottom + gap + this.config.spotlightPadding;
                const left = Math.max(8, Math.min(targetRect.left + targetRect.width / 2 - tooltipWidth / 2, vw - tooltipWidth - 8));
                if (top + tooltipHeight < vh)
                    return { top, left, arrowDirection: 'top' };
                break;
            }
            case 'top': {
                const top = targetRect.top - tooltipHeight - gap - this.config.spotlightPadding;
                const left = Math.max(8, Math.min(targetRect.left + targetRect.width / 2 - tooltipWidth / 2, vw - tooltipWidth - 8));
                if (top > 0)
                    return { top, left, arrowDirection: 'bottom' };
                break;
            }
            case 'right': {
                const top = Math.max(8, targetRect.top + targetRect.height / 2 - tooltipHeight / 2);
                const left = targetRect.right + gap + this.config.spotlightPadding;
                if (left + tooltipWidth < vw)
                    return { top, left, arrowDirection: 'left' };
                break;
            }
            case 'left': {
                const top = Math.max(8, targetRect.top + targetRect.height / 2 - tooltipHeight / 2);
                const left = targetRect.left - tooltipWidth - gap - this.config.spotlightPadding;
                if (left > 0)
                    return { top, left, arrowDirection: 'right' };
                break;
            }
        }
        // Fallback: below
        return {
            top: targetRect.bottom + gap + this.config.spotlightPadding,
            left: Math.max(8, Math.min(targetRect.left + targetRect.width / 2 - tooltipWidth / 2, vw - tooltipWidth - 8)),
            arrowDirection: 'top',
        };
    }
    bindTooltipEvents(step) {
        if (!this.tooltipEl)
            return;
        // Navigation buttons
        const buttons = this.tooltipEl.querySelectorAll('[data-action]');
        for (let i = 0; i < buttons.length; i++) {
            const btn = buttons[i];
            btn.addEventListener('click', () => {
                const action = btn.getAttribute('data-action');
                switch (action) {
                    case 'next':
                        this.next();
                        break;
                    case 'back':
                        this.back();
                        break;
                    case 'skip':
                        this.next();
                        break;
                    case 'hint':
                        this.hintVisible = true;
                        this.renderStep();
                        break;
                    case 'submit':
                        if (this.selectedQuizAnswer) {
                            const correct = this.selectedQuizAnswer === step.quizCorrectId;
                            this.events.emit('overlay:quiz-answer', {
                                stepId: step.id,
                                answerId: this.selectedQuizAnswer,
                                correct,
                            });
                            if (correct) {
                                setTimeout(() => this.next(), 600);
                            }
                        }
                        break;
                }
                if (action && action !== 'hint' && action !== 'submit') {
                    this.events.emit('overlay:action', { action: action });
                }
            });
        }
        // Quiz option selection
        const quizBtns = this.tooltipEl.querySelectorAll('[data-quiz-id]');
        for (let i = 0; i < quizBtns.length; i++) {
            const btn = quizBtns[i];
            btn.addEventListener('click', () => {
                this.selectedQuizAnswer = btn.getAttribute('data-quiz-id');
                this.renderStep();
            });
        }
    }
    label(key) {
        var _a, _b;
        const labels = BUTTON_LABELS[key];
        if (!labels)
            return key;
        return (_b = (_a = labels[this.config.locale]) !== null && _a !== void 0 ? _a : labels['en']) !== null && _b !== void 0 ? _b : key;
    }
    escapeHtml(text) {
        return text
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;');
    }
    /** Dispose the overlay and all DOM elements. */
    dispose() {
        this.hide();
    }
}

export { TutorialOverlay };
//# sourceMappingURL=TutorialOverlay.js.map
