import base64
import streamlit as st
from pathlib import Path

st.set_page_config(page_title="PptxViewJS – Streamlit Example", layout="wide")

st.title("PptxViewJS – Streamlit Example")
st.markdown("Upload a .pptx file to render it in the browser using PptxViewJS.")

uploaded = st.file_uploader("Choose a PPTX file", type=["pptx"]) 

canvas_width = st.slider("Canvas width (px)", 640, 1600, 960, 10)
canvas_height = int(canvas_width * 9 / 16)

if uploaded is not None:
    data = uploaded.read()
    b64 = base64.b64encode(data).decode("ascii")

    bundle_path = Path(__file__).resolve().parents[1] / "dist" / "PptxViewJS.min.js"
    if not bundle_path.exists():
        st.error("dist/PptxViewJS.min.js not found. Run `npm run build:min` before launching this app.")
        st.stop()
    bundle_base64 = base64.b64encode(bundle_path.read_bytes()).decode("ascii")

    # Inline HTML/JS component using PptxViewJS from dist
    # Assumes you run Streamlit from repository root so ../dist path is valid.
    html = f"""
    <!doctype html>
    <html>
    <head>
      <meta charset='utf-8' />
      <meta name='viewport' content='width=device-width, initial-scale=1' />
      <style>
        body {{ margin:0; font-family: system-ui, -apple-system, Segoe UI, Arial, sans-serif; }}
        .toolbar {{ padding:8px; border-bottom: 1px solid #eee; display:flex; gap:8px; align-items:center; }}
        #canvas {{ width: 100%; height: auto; border:1px solid #ddd; border-radius:4px; background:#fff; display:block; }}
        .status {{ color:#666; font-size:12px; margin-left:auto; }}
        .wrap {{ padding: 10px; }}
      </style>
    </head>
    <body>
      <!-- Load peer dependencies and library bundle -->
      <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script>
      <script src="../dist/PptxViewJS.min.js"></script>
      <div class="toolbar">
        <button id="prev">Prev</button>
        <button id="next">Next</button>
        <span id="status" class="status"></span>
      </div>
      <div class="wrap">
        <canvas id="canvas" width="{canvas_width}" height="{canvas_height}"></canvas>
      </div>
      <script>
        (function() {{
          const bundleBase64 = "{bundle_base64}";
          const desiredWidth = {canvas_width};
          const canvas = document.getElementById('canvas');
          const prev = document.getElementById('prev');
          const next = document.getElementById('next');
          const status = document.getElementById('status');

          prev.disabled = true;
          next.disabled = true;
          status.textContent = 'Loading viewer...';

          function postFrameHeight() {{
            try {{
              const bodyHeight = document.body ? document.body.scrollHeight : 600;
              const target = Math.max(bodyHeight + 40, desiredWidth * 0.75);
              window.parent.postMessage({{ type: 'streamlit:setFrameHeight', height: target }}, '*');
            }} catch (_err) {{}}
          }}

          function loadBundleFromBase64(b64) {{
            return new Promise(function(resolve, reject) {{
              try {{
                const binary = atob(b64);
                const len = binary.length;
                const bytes = new Uint8Array(len);
                for (let i = 0; i < len; i += 1) {{
                  bytes[i] = binary.charCodeAt(i);
                }}
                const blob = new Blob([bytes], {{ type: 'application/javascript' }});
                const url = URL.createObjectURL(blob);
                const script = document.createElement('script');
                script.type = 'application/javascript';
                script.onload = function() {{
                  URL.revokeObjectURL(url);
                  resolve();
                }};
                script.onerror = function(err) {{
                  URL.revokeObjectURL(url);
                  reject(err);
                }};
                script.src = url;
                document.head.appendChild(script);
              }} catch (err) {{
                reject(err);
              }}
            }});
          }}

          function b64ToUint8Array(b64) {{
            const binary = atob(b64);
            const len = binary.length;
            const bytes = new Uint8Array(len);
            for (let i = 0; i < len; i += 1) {{
              bytes[i] = binary.charCodeAt(i);
            }}
            return bytes;
          }}

          function applyCanvasAspect(viewerInstance) {{
            const processor = viewerInstance && viewerInstance.processor;
            if (!processor || typeof processor.getSlideDimensions !== 'function') {{
              return;
            }}
            const dims = processor.getSlideDimensions();
            if (!dims || !dims.cx || !dims.cy) {{
              return;
            }}
            const aspect = dims.cy / dims.cx;
            const targetWidth = desiredWidth;
            const targetHeight = Math.max(120, Math.round(targetWidth * aspect));
            canvas.style.width = targetWidth + 'px';
            canvas.style.height = targetHeight + 'px';
            canvas.width = targetWidth;
            canvas.height = targetHeight;
            const wrap = document.querySelector('.wrap');
            if (wrap) {{
              wrap.style.width = targetWidth + 'px';
              wrap.style.maxWidth = targetWidth + 'px';
            }}
            postFrameHeight();
          }}

          loadBundleFromBase64(bundleBase64)
            .then(function() {{
              const api = window.PptxViewJS || {{}};
              const PPTXViewer = api.PPTXViewer;
              if (!PPTXViewer) {{
                throw new Error('PptxViewJS namespace not found after bundle load.');
              }}

              const viewer = new PPTXViewer({{ canvas }});

              function updateStatus() {{
                const total = viewer.getSlideCount();
                const idx = typeof viewer.getCurrentSlideIndex === 'function'
                  ? viewer.getCurrentSlideIndex()
                  : 0;
                status.textContent = total ? 'Slide ' + (idx + 1) + ' / ' + total : '';
                prev.disabled = idx <= 0 || total <= 1;
                next.disabled = idx >= total - 1 || total <= 1;
                postFrameHeight();
              }}

              viewer.on && viewer.on('renderComplete', function() {{
                updateStatus();
              }});
              viewer.on && viewer.on('loadComplete', function() {{
                applyCanvasAspect(viewer);
                updateStatus();
              }});

              const bytes = b64ToUint8Array('{b64}');
              viewer.loadFile(bytes)
                .then(function() {{
                  applyCanvasAspect(viewer);
                  return viewer.render(canvas, {{ slideIndex: 0 }});
                }})
                .then(updateStatus)
                .catch(function(err) {{
                  console.error(err);
                  status.textContent = 'Error rendering presentation';
                  postFrameHeight();
                }});

              prev.addEventListener('click', function() {{
                viewer.previousSlide(canvas).then(function() {{
                  updateStatus();
                }});
              }});

              next.addEventListener('click', function() {{
                viewer.nextSlide(canvas).then(function() {{
                  updateStatus();
                }});
              }});

              updateStatus();
              postFrameHeight();
            }})
            .catch(function(err) {{
              console.error(err);
              status.textContent = 'Failed to load viewer bundle';
              postFrameHeight();
            }});
        }})();
      </script>
    </body>
    </html>
    """

    component_height = int(canvas_width * 1.1 + 200)
    st.components.v1.html(html, height=component_height)
else:
    st.info("Upload a .pptx file to start.")
