#pragma once
#include <U8g2lib.h>
#include "BreakoutGame.h"
#include "MicroRacerGame.h"
#include "DefenderMiniGame.h"
#include "JumpGame.h"
#include "HeliCaveGame.h"

namespace MobileGames {
U8G2_SSD1306_128X64_NONAME_F_HW_I2C canvas(U8G2_R0,U8X8_PIN_NONE,4,3);
BreakoutGame breakout(70,40,1);
MicroRacerGame racer(70,40,1);
DefenderMiniGame defender(70,40,1);
JumpGame jump(70,40,1);
HeliCaveGame heli(70,40,1);
Game* games[]={&breakout,&racer,&defender,&jump,&heli};
constexpr uint8_t count=5;
SingleButton menuButton;
bool entered=false, menu=true, waitingRelease=true, suspended=false;
uint8_t index=0;
uint32_t rendered=0, heldSince=0;
bool holding=false;

void enter(uint32_t now) {
  entered=true;
  menu=true;
  waitingRelease=true;
  holding=false;
  menuButton.reset(false,now);
}

bool tick(Adafruit_SSD1306& display,uint32_t now,bool down,bool overlay) {

  if (!entered) {

    enter(now);

  }

  if (overlay) {

    suspended=true;
    return false;

  }

  if (suspended) {

    // Restart at the game menu after a bell/silence: no giant simulation delta.
    suspended=false;
    enter(now);

  }

  if (waitingRelease) {

    if (down) {

      return false;

    }

    waitingRelease=false;
    menuButton.reset(false,now);

  }

  if (down && !holding) {

    holding=true;
    heldSince=now;

  }

  if (!down) {

    holding=false;

  }

  if (!menu && holding && now-heldSince>=4000) {

    enter(now);
    return false;

  }

  if (menu) {

    auto input=menuButton.update(down,now);

    if (input.click) {

      index=(index+1)%(count+1);

    }

    if (input.longPress) {

      if (index==count) {

        entered=false;
        return true;

      }

      games[index]->begin(now,false);
      menu=false;
      holding=false;
      waitingRelease=true;

    }

  } else {

    games[index]->tick(now,down);

    if (games[index]->shouldExitToMenu()) {

      games[index]->clearExitRequest();
      enter(now);

    }

  }

  if (now-rendered<33) {

    return false;

  }

  rendered=now;
  canvas.clearBuffer();
  canvas.setFont(u8g2_font_5x8_tr);

  if (menu) {

    canvas.drawStr(4,12,"MINI ARCADE");
    canvas.drawStr(4,30,index==count?"Back to pet":games[index]->gameTitle());
    canvas.drawStr(4,46,"Tap: next");
    canvas.drawStr(4,59,"Hold: select");

  } else {

    games[index]->render(canvas);

    if (games[index]->phase()!=GamePhase::Running) {

      canvas.drawStr(4,12,games[index]->gameTitle());
      canvas.drawStr(4,30,games[index]->phase()==GamePhase::End?"Game over":"Ready?");
      canvas.drawStr(4,44,"Tap: play");
      canvas.drawStr(4,59,"Hold 4s: menu");

    }

  }

  // Same SSD1306 page buffer layout; only the existing display driver owns I2C.
  if (!menu && games[index]->phase()==GamePhase::Running) {

    // Preserve upstream 72x40 coordinates and physics; scale pixels into 115x64.
    display.clearDisplay();
    const uint8_t* source=canvas.getBufferPtr();

    for (int y=0;y<64;++y) {

      int sy=y*40/64;

      for (int x=0;x<115;++x) {

        int sx=x*72/115;

        if (source[(sy/8)*128+sx] & (1u<<(sy%8))) {

          display.drawPixel(x+6,y,SSD1306_WHITE);

        }

      }

    }

  } else {

    memcpy(display.getBuffer(),canvas.getBufferPtr(),1024);

  }
  display.display();
  return false;
}
}
