const { useState: useStateApp, useEffect: useEffectApp, useRef: useRefApp, useCallback: useCallbackApp } = React;

/* audio (8-bit beeps) */
let audioCtx = null;
function getAudioCtx() {
  if (!audioCtx) {
    try { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); }
    catch (e) { audioCtx = null; }
  }
  return audioCtx;
}
function beep(freq=440, dur=80, type='square', vol=0.06) {
  const ctx = getAudioCtx();
  if (!ctx) return;
  const o = ctx.createOscillator();
  const g = ctx.createGain();
  o.type = type;
  o.frequency.value = freq;
  g.gain.value = vol;
  o.connect(g); g.connect(ctx.destination);
  o.start();
  g.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + dur/1000);
  o.stop(ctx.currentTime + dur/1000 + 0.02);
}
const sfx = {
  open: () => { beep(660, 50); setTimeout(() => beep(880, 60), 50); },
  close: () => { beep(440, 50); setTimeout(() => beep(220, 70), 50); },
  click: () => beep(1200, 25, 'square', 0.04),
  error: () => { beep(220, 90); setTimeout(() => beep(180, 110), 100); },
  ding:  () => { beep(880, 60); setTimeout(() => beep(1320, 80), 70); },
  startup: () => {
    [262, 330, 392, 523].forEach((f, i) => setTimeout(() => beep(f, 110, 'square', 0.05), i*120));
  },
};

const DESKTOP_ICONS = [
  { id: 'about',     name: 'About Me',        icon: '/img/about me.png?v=14', kind: 'about' },
  { id: 'projects',  name: 'Case Studies',    icon: '/img/folder.png?v=14',   kind: 'folder-projects' },
  { id: 'sideprojects', name: 'Side Projects', icon: '/img/folder.png?v=14',  kind: 'folder-sideprojects' },
  { id: 'writings',  name: 'Writings',        icon: '/img/folder.png?v=14',   kind: 'folder-writings' },
  { id: 'games',     name: 'Games',           icon: '/img/games.png?v=14',    kind: 'folder-games' },
  { id: 'music',     name: 'Music',           icon: '/img/music.png?v=14',    kind: 'music' },
  { id: 'guestbook', name: 'Contact Me',      icon: '/img/guestbook.png?v=14',     kind: 'guestbook' },
  { id: 'resume',    name: 'Resume.pdf',      icon: '/img/resume2.png?v=14',   kind: 'resume' },
  { id: 'p_favorited',  name: 'Favorited',    icon: '/img/fav_pixel.png?v=14',      kind: 'project', projectId: 'favorited' },
  { id: 'p_polywork',   name: 'Polywork',     icon: '/img/polywork_pixel.png?v=14', kind: 'project', projectId: 'polywork' },
  { id: 'p_anchorage',  name: 'Anchorage',    icon: '/img/anchorage_pixel.png?v=14',   kind: 'project', projectId: 'anchorage' },
  { id: 'p_fizz',        name: 'Fizz',         icon: '/img/fizz_pixel.png?v=14',  kind: 'project', projectId: 'fizz' },
  { id: 'p_lime',       name: 'Lime',         icon: '/img/lime_pixel.png?v=14', kind: 'project', projectId: 'lime' },
  { id: 'p_avail',      name: 'Avail',        icon: '/img/avil_pixel.png?v=14',     kind: 'project', projectId: 'avail' },
  { id: 'trash',     name: 'Recycle Bin',     icon: '/img/bin_full.png?v=14', kind: 'trash' },
];

function DesktopIcon({ item, selected, onSelect, onOpen }) {
  return (
    <button
      className={`desktop-icon ${selected ? 'selected' : ''}`}
      onClick={(e) => { e.stopPropagation(); onSelect(item.id); }}
      onDoubleClick={(e) => { e.stopPropagation(); onOpen(item); }}
    >
      <img className="icon-img" src={item.icon} alt="" />
      <div className="icon-label">{item.name}</div>
    </button>
  );
}

function App() {
  const [soundOn, setSoundOn] = useStateApp(false);
  const [windows, setWindows] = useStateApp([]);
  const zCounter = useRefApp(100);
  const [activeId, setActiveId] = useStateApp(null);
  const [selectedIconId, setSelectedIconId] = useStateApp(null);
  const [startOpen, setStartOpen] = useStateApp(false);
  const [clock, setClock] = useStateApp(formatClock());
  const [dialog, setDialog] = useStateApp(null);
  const [mascotMsg, setMascotMsg] = useStateApp(null);
  const [mascotHidden, setMascotHidden] = useStateApp(false);
  const [csHistory, setCsHistory] = useStateApp([]);
  const soundRef = useRefApp(soundOn);
  soundRef.current = soundOn;

  function formatClock() {
    const d = new Date();
    let h = d.getHours();
    const m = d.getMinutes().toString().padStart(2, '0');
    const ap = h >= 12 ? 'PM' : 'AM';
    h = h % 12; if (h === 0) h = 12;
    return h + ':' + m + ' ' + ap;
  }

  useEffectApp(() => {
    const t = setInterval(() => setClock(formatClock()), 15000);
    return () => clearInterval(t);
  }, []);

  useEffectApp(() => {
    setTimeout(() => {
      openWindow({
        kind: 'about',
        title: 'About — David Ciaffoni',
        icon: '/img/about me.png?v=14',
        w: 620, h: 400,
      });
    }, 400);
    setTimeout(() => {
      setMascotMsg({
        text: "Hi! I'm Mickey — David's desktop assistant. What would you like to explore?",
        actions: [
          { id: 'open_cases',  label: 'Open Case Studies' },
          { id: 'open_side',   label: 'Open Side Projects' },
          { id: 'send_note',   label: 'Contact David' },
        ],
      });
    }, 1400);
  }, []);

  const playSfx = (name) => { if (soundRef.current) sfx[name] && sfx[name](); };

  const openWindow = useCallbackApp((spec) => {
    const id = spec.id || 'w-' + Date.now() + '-' + Math.random().toString(36).slice(2,7);
    zCounter.current += 1;
    const w = {
      id,
      kind: spec.kind,
      title: spec.title,
      icon: spec.icon,
      payload: spec.payload,
      w: spec.w ?? 520,
      h: spec.h ?? 380,
      x: spec.x ?? Math.round((window.innerWidth - (spec.w ?? 520)) / 2) + (zCounter.current % 6) * 16,
      y: spec.y ?? Math.round((window.innerHeight - 32 - (spec.h ?? 380)) / 3) + (zCounter.current % 6) * 14,
      z: zCounter.current,
      minimized: false,
    };
    setWindows(prev => {
      if (spec.singleton) {
        const existing = prev.find(p => p.kind === spec.kind);
        if (existing) { setActiveId(existing.id); return prev.map(p => p.id === existing.id ? {...p, z: zCounter.current, minimized: false} : p); }
      }
      return [...prev, w];
    });
    setActiveId(id);
  }, []);

  const closeWindow = (id) => {
    setWindows(prev => prev.filter(w => w.id !== id));
    if (activeId === id) setActiveId(null);
  };
  const focusWindow = (id) => {
    if (activeId === id) return;
    zCounter.current += 1;
    setWindows(prev => prev.map(w => w.id === id ? { ...w, z: zCounter.current, minimized: false } : w));
    setActiveId(id);
  };
  const minWindow = (id) => {
    setWindows(prev => prev.map(w => w.id === id ? { ...w, minimized: true } : w));
    if (activeId === id) setActiveId(null);
  };

  const openDesktopItem = (item) => {
    playSfx('open');
    setStartOpen(false);
    if (item.kind === 'about') {
      openWindow({
        kind: 'about',
        title: 'About — David Ciaffoni',
        icon: '/img/about me.png?v=14',
        w: 620, h: 420,
      });
    } else if (item.kind === 'folder-projects') {
      openWindow({
        singleton: true, kind: 'folder-projects',
        title: 'Case Studies',
        icon: '/img/folder.png?v=14',
        w: 520, h: 360,
      });
    } else if (item.kind === 'folder-sideprojects') {
      openWindow({
        singleton: true, kind: 'folder-sideprojects',
        title: 'Side Projects',
        icon: '/img/folder.png?v=14',
        w: 400, h: 280,
      });
    } else if (item.kind === 'folder-writings') {
      openWindow({
        singleton: true, kind: 'folder-writings',
        title: 'Writings',
        icon: '/img/folder.png?v=14',
        w: 460, h: 280,
      });
    } else if (item.kind === 'folder-games') {
      openWindow({
        singleton: true, kind: 'folder-games',
        title: 'Games',
        icon: '/img/games.png?v=14',
        w: 360, h: 240,
      });
    } else if (item.kind === 'music') {
      openWindow({
        singleton: true, kind: 'music',
        title: 'Music — Spotify',
        icon: '/img/music.png?v=14',
        w: 400, h: 500,
      });
    } else if (item.kind === 'illusion') {
      var iw = Math.min(900, window.innerWidth - 100);
      var ih = Math.min(650, window.innerHeight - 80);
      openWindow({
        singleton: true, kind: 'illusion',
        title: 'Illusion.ai',
        icon: '/img/folder.png?v=14',
        w: iw, h: ih,
      });
    } else if (item.kind === 'guestbook') {
      openWindow({
        singleton: true, kind: 'guestbook',
        title: 'New Message — Contact Me',
        icon: '/img/guestbook.png?v=14',
        w: 520, h: 440,
      });
    } else if (item.kind === 'resume') {
      window.open('https://www.dropbox.com/scl/fi/9k7w8xd2ofp641cjlyez9/David-Ciaffoni_Senior-Designer_20260128_updated.pdf?rlkey=tiregmq2ha6ynh0a21lheam1a&st=x6ntt9dj&dl=0', '_blank');
    } else if (item.kind === 'project') {
      const p = PROJECTS.find(p => p.id === item.projectId);
      openProject(p);
    } else if (item.kind === 'trash') {
      openWindow({
        singleton: true, kind: 'trash',
        title: 'Recycle Bin',
        icon: '/img/bin_full.png?v=14',
        w: 520, h: 340,
      });
    }
  };

  const openProject = (project) => {
    if (!project) return;
    setCsHistory(h => [...h, project.id]);
    setWindows(prev => {
      const existing = prev.find(w => w.kind === 'browser');
      if (existing) {
        zCounter.current += 1;
        return prev.map(w => w.id === existing.id
          ? { ...w, payload: { project }, title: project.name + ' — Portfolio Explorer', z: zCounter.current, minimized: false }
          : w);
      }
      zCounter.current += 1;
      var bw = Math.min(900, window.innerWidth - 100);
      var bh = Math.min(650, window.innerHeight - 80);
      return [...prev, {
        id: 'browser-singleton',
        kind: 'browser',
        title: project.name + ' — Portfolio Explorer',
        icon: '/icons/icon-computer.svg?v=14',
        payload: { project },
        x: Math.round((window.innerWidth - bw) / 2),
        y: Math.round((window.innerHeight - bh - 32) / 2),
        w: bw, h: bh, z: zCounter.current, minimized: false,
      }];
    });
    setActiveId('browser-singleton');
  };

  const browserNav = (action) => {
    if (action === 'back') {
      setCsHistory(h => {
        const next = h.slice(0, -1);
        const prevId = next[next.length - 1];
        if (prevId) {
          const p = PROJECTS.find(p => p.id === prevId);
          setWindows(ws => ws.map(w => w.kind === 'browser' ? { ...w, payload: { project: p }, title: p.name + ' — Portfolio Explorer' } : w));
        } else {
          setWindows(ws => ws.map(w => w.kind === 'browser' ? { ...w, payload: { project: null }, title: 'Portfolio Explorer' } : w));
        }
        return next;
      });
    } else if (action === 'home') {
      setWindows(ws => ws.map(w => w.kind === 'browser' ? { ...w, payload: { project: null }, title: 'Portfolio Explorer' } : w));
      setCsHistory([]);
    }
  };

  const funFactIndex = useRefApp(0);
  const FUN_FACTS = [
    "David was the first full-time designer at Lime — before scooters even existed in the app!",
    "David once designed 47 versions of a logo before the client picked version 3.",
    "David's guilty pleasure is ranking Beatles solo albums. He has strong opinions.",
    "David built a space arcade game called Singularity that's on the App Store with a 4.7 rating!",
    "David's design motto: if it needs a tutorial, it needs a redesign.",
    "David recently launched illusion.ai, an AI SEO platform for GEO (Generative Engine Optimization) and AEO (Answer Engine Optimization) meant to compete with and call out the overvalued and overpriced YC/VC backed startups like AthenaHQ and Profound.",
  ];

  const onMascotAction = (id) => {
    playSfx('click');
    if (id === 'open_cases') { openDesktopItem({ kind: 'folder-projects' }); setMascotMsg(null); }
    else if (id === 'open_side') { openDesktopItem({ kind: 'folder-sideprojects' }); setMascotMsg(null); }
    else if (id === 'open_proj') { openDesktopItem({ kind: 'folder-projects' }); setMascotMsg(null); }
    else if (id === 'show_lime') { openProject(PROJECTS.find(p => p.id === 'lime')); setMascotMsg(null); }
    else if (id === 'visit_illusion') { openDesktopItem({ kind: 'illusion' }); setMascotMsg(null); }
    else if (id === 'fun_fact') {
      var fact = FUN_FACTS[funFactIndex.current % FUN_FACTS.length];
      funFactIndex.current++;
      var actions = [
        { id: 'fun_fact', label: 'Another one!' },
        { id: 'back_to_menu', label: 'Back' },
      ];
      if (fact.indexOf('illusion.ai') !== -1) {
        actions.unshift({ id: 'visit_illusion', label: 'Visit Illusion.ai' });
      }
      setMascotMsg({ text: fact, actions: actions });
    }
    else if (id === 'send_note') { openDesktopItem({ kind: 'guestbook' }); setMascotMsg(null); }
    else if (id === 'greet' || id === 'back_to_menu') {
      setMascotMsg({
        text: "Hey! I'm Mickey — David's desktop assistant. What can I help with?",
        actions: [
          { id: 'open_cases',  label: 'Open Case Studies' },
          { id: 'open_side',   label: 'Open Side Projects' },
          { id: 'fun_fact',    label: 'Fun Fact' },
          { id: 'send_note',   label: 'Contact David' },
          { id: 'dismiss',     label: 'Dismiss' },
        ],
      });
    }
    else if (id === 'dismiss') setMascotMsg(null);
  };

  const onGuestbookSend = (msg) => {
    if (!msg.name || !msg.body) {
      playSfx('error');
      setDialog({
        title: 'Cannot Send Message',
        icon: '/icons/icon-mail.svg?v=14',
        body: 'Please fill in your name and a message body before sending.',
        buttons: [{ label: 'OK', primary: true, onClick: () => setDialog(null) }],
      });
      return;
    }
    playSfx('ding');
    setDialog({
      title: 'Sending...',
      icon: '/icons/icon-mail.svg?v=14',
      body: 'Sending your message...',
      buttons: [],
    });
    fetch('https://api.staticforms.dev/submit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        apiKey: 'sf_649ba0d023f3ad7f60623de6',
        subject: msg.subject || 'Contact form submission',
        name: msg.name,
        email: msg.email,
        message: msg.body,
        replyTo: msg.email,
      }),
    }).then(function(res) { return res.json(); })
    .then(function(data) {
      if (data.success) {
        playSfx('ding');
        setDialog({
          title: 'Message Sent',
          icon: '/icons/icon-mail.svg?v=14',
          body: 'Your message has been sent. Thanks, ' + msg.name + '!',
          buttons: [{ label: 'OK', primary: true, onClick: () => {
            setDialog(null);
            setWindows(prev => prev.filter(w => w.kind !== 'guestbook'));
          }}],
        });
      } else {
        throw new Error('Send failed');
      }
    }).catch(function() {
      playSfx('error');
      setDialog({
        title: 'Send Failed',
        icon: '/icons/icon-mail.svg?v=14',
        body: 'Could not send your message. Please try emailing david@bestdavid.com directly.',
        buttons: [{ label: 'OK', primary: true, onClick: () => setDialog(null) }],
      });
    });
  };

  const onTrashItem = (item) => {
    playSfx('error');
    setDialog({
      title: 'File Access Denied',
      icon: '/img/bin_full.png?v=14',
      body: item.name + '\n\n' + item.note + '\n\nThis file is in the Recycle Bin and cannot be opened.',
      buttons: [{ label: 'OK', primary: true, onClick: () => setDialog(null) }],
    });
  };

  function renderWindowBody(w) {
    switch (w.kind) {
      case 'about':            return <AboutContent />;
      case 'folder-projects':  return <ProjectsFolder onOpen={openProject} />;
      case 'folder-sideprojects': return <SideProjectsFolder onOpenIllusion={() => openDesktopItem({ kind: 'illusion' })} />;
      case 'folder-games':     return <GamesFolder />;
      case 'folder-writings':  return <WritingsFolder onOpen={(wr) => {
        if (wr.pdfUrl) {
          var pw = Math.min(900, window.innerWidth - 100);
          var ph = Math.min(720, window.innerHeight - 80);
          openWindow({
            kind: 'pdf',
            title: wr.title + ' — Reader',
            icon: '/img/textfile.png?v=14',
            w: pw, h: ph,
            payload: { url: wr.pdfUrl },
          });
        } else {
          openWindow({
            kind: 'notepad',
            title: wr.name + ' — Notepad',
            icon: '/img/textfile.png?v=14',
            w: 480, h: 360,
            payload: { writing: wr },
          });
        }
      }} />;
      case 'notepad':          return <Notepad writing={w.payload.writing} />;
      case 'pdf':              return <iframe src={w.payload.url} style={{width:'100%',flex:1,border:'none',background:'#fff'}} />;
      case 'music':            return <iframe src="https://open.spotify.com/embed/playlist/37i9dQZF1CKZu9GyiMGypn?utm_source=generator&theme=0" style={{width:'100%',flex:1,border:'none',borderRadius:0}} allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" />;
      case 'illusion':         return <iframe src="https://illusion.ai" style={{width:'100%',flex:1,border:'none',background:'#fff'}} />;
      case 'guestbook':        return <Guestbook onSend={onGuestbookSend} />;
      case 'trash':            return <Trash onItemClick={onTrashItem} />;
      case 'browser':          return <CaseStudyView project={w.payload?.project} onNav={browserNav} onOpenProject={openProject} />;
      default:                 return null;
    }
  }

  return (
    <div
      id="desktop"
      onMouseDown={(e) => {
        if (e.target.id === 'desktop' || e.target.classList?.contains('desktop-grid')) {
          setSelectedIconId(null);
          setStartOpen(false);
        }
      }}
    >
      <div className="desktop-grid">
        {DESKTOP_ICONS.map(item => (
          <DesktopIcon
            key={item.id}
            item={item}
            selected={selectedIconId === item.id}
            onSelect={setSelectedIconId}
            onOpen={openDesktopItem}
          />
        ))}
      </div>

      {windows.filter(w => !w.minimized).map(w => (
        <Win
          key={w.id}
          id={w.id}
          title={w.title}
          icon={w.icon}
          x={w.x} y={w.y} w={w.w} h={w.h} z={w.z}
          active={activeId === w.id}
          onFocus={focusWindow}
          onClose={(id) => { playSfx('close'); closeWindow(id); }}
          onMin={minWindow}
          statusBar={
            w.kind === 'browser'
              ? <><div className="seg">Done</div><div className="seg" style={{flex:0,minWidth:140}}>&#127760; Local Intranet</div></>
              : null
          }
        >
          {renderWindowBody(w)}
        </Win>
      ))}

      {!mascotHidden && (
        <Mascot
          message={mascotMsg}
          onAction={onMascotAction}
          onDismiss={() => { setMascotMsg(null); }}
        />
      )}

      {dialog && (
        <Dialog
          title={dialog.title}
          icon={dialog.icon}
          body={dialog.body}
          buttons={dialog.buttons}
          onClose={() => setDialog(null)}
        />
      )}

      {startOpen && (
        <div className="start-menu" onMouseDown={(e) => e.stopPropagation()}>
          <div className="start-menu-rail">PORTFOLIO<b>95</b></div>
          <div className="start-menu-list">
            <div className="start-menu-item" onClick={() => { openDesktopItem({kind:'folder-projects'}); }}>
              <img src="/img/folder.png" alt="" /><span><u>C</u>ase Studies</span>
            </div>
            <div className="start-menu-item" onClick={() => { openDesktopItem({kind:'folder-sideprojects'}); }}>
              <img src="/img/folder.png" alt="" /><span><u>S</u>ide Projects</span>
            </div>
            <div className="start-menu-item" onClick={() => { openDesktopItem({kind:'folder-writings'}); }}>
              <img src="/img/folder.png" alt="" /><span><u>W</u>ritings</span>
            </div>
            <div className="start-menu-item" onClick={() => { openDesktopItem({kind:'folder-games'}); }}>
              <img src="/img/games.png" alt="" /><span><u>G</u>ames</span>
            </div>
            <div className="start-menu-item" onClick={() => { openDesktopItem({kind:'about'}); }}>
              <img src="/img/about me.png" alt="" /><span><u>A</u>bout Me</span>
            </div>
            <div className="start-menu-item" onClick={() => { openDesktopItem({kind:'resume'}); }}>
              <img src="/img/resume.png" alt="" /><span><u>R</u>esume.pdf</span>
            </div>
            <div className="start-menu-sep"></div>
            <div className="start-menu-item" onClick={() => { openDesktopItem({kind:'guestbook'}); }}>
              <img src="/img/guestbook.png" alt="" /><span><u>C</u>ontact Me</span>
            </div>
            <div className="start-menu-item" onClick={() => { openDesktopItem({kind:'trash'}); }}>
              <img src="/img/bin_full.png" alt="" /><span>Recycle <u>B</u>in</span>
            </div>
            <div className="start-menu-sep"></div>
            <div className="start-menu-item" onClick={() => {
              setStartOpen(false);
              setDialog({
                title: "Shut Down — David's Webpage",
                icon: '/icons/icon-computer.svg?v=14',
                body: "Are you sure you want to exit the portfolio?\n\n(You can also just close the tab. We won't take it personally.)",
                buttons: [
                  { label: 'Yes', primary: true, onClick: () => {
                    setDialog({
                      title: 'It is now safe...',
                      body: 'It is now safe to close this window.',
                      buttons: [{ label: 'OK', primary: true, onClick: () => setDialog(null) }],
                    });
                  }},
                  { label: 'No', onClick: () => setDialog(null) },
                ],
              });
            }}>
              <img src="/img/shut_down.png?v=14" alt="" /><span>Sh<u>u</u>t Down...</span>
            </div>
          </div>
        </div>
      )}

      <div className="taskbar" onMouseDown={(e) => e.stopPropagation()}>
        <button
          className={'start-btn ' + (startOpen ? 'active' : '')}
          onClick={() => { playSfx('click'); setStartOpen(v => !v); }}
        >
          <img className="start-btn-flag" src="/img/start.png?v=14" alt="" />
          Start
        </button>
        <div className="taskbar-divider"></div>
        <div className="task-buttons">
          {windows.map(w => (
            <button
              key={w.id}
              className={'task-btn ' + (activeId === w.id && !w.minimized ? 'active' : '')}
              onClick={() => {
                if (w.minimized) focusWindow(w.id);
                else if (activeId === w.id) minWindow(w.id);
                else focusWindow(w.id);
              }}
            >
              {w.icon && <img className="ico" src={w.icon} alt="" />}
              <span className="lbl">{w.title}</span>
            </button>
          ))}
        </div>
        <div className="tray">
          <img
            className="icn"
            title="About this site"
            src="/img/help.png?v=14"
            onClick={() => {
              playSfx('click');
              setDialog({
                title: 'About — Portfolio95',
                icon: '/img/help.png?v=14',
                body: 'Made by David Ciaffoni in Santa Monica, California in 2026.',
                buttons: [{ label: 'OK', primary: true, onClick: () => setDialog(null) }],
              });
            }}
          />
          <span>{clock}</span>
        </div>
      </div>
    </div>
  );
}

var isMobileViewport = window.matchMedia('(max-width: 767px)').matches;
function Root() {
  return (
    <>
      {isMobileViewport ? <Mobile /> : <App />}
      <ScreensaverManager idleMs={180000} />
    </>
  );
}
ReactDOM.createRoot(document.getElementById('root')).render(<Root />);
