// スタートボタンの要素を取得する
const startBtn = document.getElementById("startBtn");
// リスタートボタンの要素を取得する
const restartBtn = document.getElementById("restartBtn");
// ゲーム中の画面全体を取得する
const gamePanel = document.getElementById("gamePanel");
// 結果表示エリアを取得する
const resultBox = document.getElementById("resultBox");
// 残り時間を表示する要素を取得する
const timeEl = document.getElementById("time");
// ハイスコアを表示する要素を取得する
const highScoreEl = document.getElementById("highScore");
// 最終スコアを表示する要素を取得する
const finalScoreEl = document.getElementById("finalScore");
// 新記録メッセージを表示する要素を取得する
const newRecordMsgEl = document.getElementById("newRecordMsg");
// 出題する絵文字を表示する要素を取得する
const emojiDisplayEl = document.getElementById("emojiDisplay");
// 1つ目の選択肢ボタンを取得する
const btn0 = document.getElementById("btn0");
// 2つ目の選択肢ボタンを取得する
const btn1 = document.getElementById("btn1");
// 正解したアイテムを並べる表示エリアを取得する
const itemsEl = document.getElementById("items");
// 結果画面でアイテム一覧を表示する要素を取得する
const resultItemsEl = document.getElementById("resultItems");
// 正解・不正解の記号を表示する要素を取得する
const judgeMarkEl = document.getElementById("judgeMark");

// 1回のゲーム時間を秒数で定義する
const GAME_TIME = 30;
// ハイスコア保存用のローカルストレージキーを定義する
const STORAGE_KEY = "katakana_quiz_high_score";
// 回答後に次の問題へ進むまでの待ち時間をミリ秒で定義する
const NEXT_WAIT = 800;

// クイズの元データを配列で定義する
// 絵文字・正解・ダミー選択肢を1セットで持つ
const quizData = [
  { emoji: "🍦", correct: "アイスクリーム", dummy: "マイスクリーム" },
  { emoji: "🍎", correct: "リンゴ", dummy: "リソゴ" },
  { emoji: "🍌", correct: "バナナ", dummy: "パナナ" },
  { emoji: "🚗", correct: "クルマ", dummy: "ワルマ" },
  { emoji: "🚌", correct: "バス", dummy: "パス" },
  { emoji: "🐱", correct: "ネコ", dummy: "メコ" },
  { emoji: "🍰", correct: "ケーキ", dummy: "クーキ" },
  { emoji: "🚀", correct: "ロケット", dummy: "ロケツト" },
  { emoji: "📷", correct: "カメラ", dummy: "カヌラ" },
  { emoji: "🐼", correct: "パンダ", dummy: "パソダ" },
  { emoji: "⚽", correct: "サッカー", dummy: "サツカー" },
  { emoji: "🍔", correct: "ハンバーガー", dummy: "ハソバーガー" },
  { emoji: "🐶", correct: "イヌ", dummy: "イヌ゙" },
  { emoji: "🐸", correct: "カエル", dummy: "カエレ" },
  { emoji: "🐰", correct: "ウサギ", dummy: "ワサギ" },
  { emoji: "🦁", correct: "ライオン", dummy: "ライオソ" },
  { emoji: "🐻", correct: "クマ", dummy: "クメ" },
  { emoji: "🍕", correct: "ピザ", dummy: "ビザ" },
  { emoji: "🍩", correct: "ドーナツ", dummy: "ドーナシ" },
  { emoji: "🍓", correct: "イチゴ", dummy: "イタゴ" },
  { emoji: "🍇", correct: "ブドウ", dummy: "プドウ" },
  { emoji: "🐘", correct: "ゾウ", dummy: "ソウ" },
  { emoji: "🎸", correct: "ギター", dummy: "ギクー" },
  { emoji: "🦒", correct: "キリン", dummy: "キリソ" },
  { emoji: "🥪", correct: "サンドイッチ", dummy: "サソドイッチ" },
  { emoji: "🚕", correct: "タクシー", dummy: "タクンー" },
  { emoji: "📺", correct: "テレビ", dummy: "テヘビ" }
];

// 現在の正解数を管理する変数
let score = 0;
// 残り時間を管理する変数
let timeLeft = GAME_TIME;
// 現在表示中の問題データを保持する変数
let currentQuiz = null;
// setIntervalのIDを保持する変数
let timer = null;
// 次の問題表示用setTimeoutのIDを保持する変数
let nextQuizTimeout = null;
// 保存済みハイスコアをローカルストレージから読み込む
let highScore = Number(localStorage.getItem(STORAGE_KEY) || 0);
// 回答後の待機中かどうかを判定するフラグ
let isWaitingNext = false;

// シャッフルされた問題配列を入れる変数
let shuffledQuiz = [];
// 現在どの問題まで進んだかを示すインデックス
let currentQuizIndex = 0;

// 初期表示としてハイスコア欄に値を入れる
highScoreEl.textContent = String(highScore);
// 初期表示として残り時間欄にゲーム時間を入れる
timeEl.textContent = String(GAME_TIME);

// スタートボタンが押されたらゲーム開始関数を実行する
startBtn.addEventListener("click", startGame);
// リスタートボタンが押されたらゲーム開始関数を実行する
restartBtn.addEventListener("click", startGame);
// 1つ目の選択肢が押されたら0番として判定する
btn0.addEventListener("click", () => checkAnswer(0));
// 2つ目の選択肢が押されたら1番として判定する
btn1.addEventListener("click", () => checkAnswer(1));

// ゲームを初期化して開始する関数
function startGame() {
  // 既存のタイマーがあれば停止する
  clearInterval(timer);
  // 既存の次問題タイマーがあれば停止する
  clearTimeout(nextQuizTimeout);

  // スコアを0に戻す
  score = 0;
  // 残り時間を初期値に戻す
  timeLeft = GAME_TIME;
  // 現在の問題情報を空にする
  currentQuiz = null;
  // タイマーIDを空にする
  timer = null;
  // 次問題タイマーIDを空にする
  nextQuizTimeout = null;
  // 待機中フラグを解除する
  isWaitingNext = false;

  // 問題配列をシャッフルして新しい順番を作る
  shuffledQuiz = shuffleArray(quizData);
  // 問題番号を最初に戻す
  currentQuizIndex = 0;

  // 取得済みアイテム表示を空にする
  itemsEl.innerHTML = "";
  // 結果画面のアイテム表示も空にする
  resultItemsEl.innerHTML = "";
  // 新記録メッセージを空にする
  newRecordMsgEl.textContent = "";
  // 結果画面を非表示にする
  resultBox.style.display = "none";
  // スタートボタンを非表示にする
  startBtn.style.display = "none";
  // ゲーム画面を表示する
  gamePanel.style.display = "flex";

  // 残り時間を画面に反映する
  timeEl.textContent = String(timeLeft);
  // 判定マークを隠す
  hideJudgeMark();
  // ボタン状態を初期化する
  resetButtons();

  // 最初の問題を表示する
  nextQuiz();
  // カウントダウンタイマーを開始する
  startTimer();
}

// 1秒ごとに残り時間を減らすタイマーを開始する関数
function startTimer() {
  // 二重にタイマーが動かないように既存タイマーを停止する
  clearInterval(timer);

  // 1秒ごとに処理を繰り返すタイマーをセットする
  timer = setInterval(() => {
    // 残り時間を1減らす
    timeLeft -= 1;
    // 画面の残り時間表示を更新する
    timeEl.textContent = String(timeLeft);

    // 残り時間が0以下ならゲーム終了処理を行う
    if (timeLeft <= 0) {
      endGame();
    }
  }, 1000);
}

// 配列をランダムに並び替えて返す関数
function shuffleArray(array) {
  // 元の配列を壊さないようにコピーを作る
  const newArray = [...array];

  // 配列の末尾から先頭に向かって入れ替えていく
  for (let i = newArray.length - 1; i > 0; i--) {
    // 0からiまでのランダムな位置を決める
    const j = Math.floor(Math.random() * (i + 1));
    // i番目とj番目の要素を交換する
    [newArray[i], newArray[j]] = [newArray[j], newArray[i]];
  }

  // シャッフル後の配列を返す
  return newArray;
}

// 次の問題を画面に表示する関数
function nextQuiz() {
  // ボタンの見た目と状態をリセットする
  resetButtons();
  // 判定マークを非表示にする
  hideJudgeMark();
  // 待機中フラグを解除する
  isWaitingNext = false;

  // すべての問題を出し終えたら再度シャッフルして最初に戻る
  if (currentQuizIndex >= shuffledQuiz.length) {
    // 問題配列を再シャッフルする
    shuffledQuiz = shuffleArray(quizData);
    // インデックスを最初に戻す
    currentQuizIndex = 0;
  }

  // 現在の問題として配列から1件取り出す
  currentQuiz = shuffledQuiz[currentQuizIndex];
  // 次回のためにインデックスを進める
  currentQuizIndex += 1;

  // 問題の絵文字を画面に表示する
  emojiDisplayEl.textContent = currentQuiz.emoji;

  // 正解を上に置くか下に置くかをランダムで決める
  const isCorrectAtTop = Math.random() > 0.5;

  // 正解を上側ボタンに置く場合
  if (isCorrectAtTop) {
    // 上のボタンに正解文を入れる
    btn0.textContent = currentQuiz.correct;
    // 下のボタンにダミー文を入れる
    btn1.textContent = currentQuiz.dummy;
    // 上のボタンを正解として記録する
    btn0.dataset.correct = "1";
    // 下のボタンを不正解として記録する
    btn1.dataset.correct = "0";
  } else {
    // 上のボタンにダミー文を入れる
    btn0.textContent = currentQuiz.dummy;
    // 下のボタンに正解文を入れる
    btn1.textContent = currentQuiz.correct;
    // 上のボタンを不正解として記録する
    btn0.dataset.correct = "0";
    // 下のボタンを正解として記録する
    btn1.dataset.correct = "1";
  }
}

// 選択ボタンの見た目と無効状態を元に戻す関数
function resetButtons() {
  // 1つ目のボタンからwrongとdisabledクラスを外す
  btn0.classList.remove("wrong", "disabled");
  // 2つ目のボタンからwrongとdisabledクラスを外す
  btn1.classList.remove("wrong", "disabled");
}

// 選択ボタンを押せない状態にする関数
function lockButtons() {
  // 1つ目のボタンにdisabledクラスを付ける
  btn0.classList.add("disabled");
  // 2つ目のボタンにdisabledクラスを付ける
  btn1.classList.add("disabled");
}

// 正解または不正解の記号を表示する関数
function showJudgeMark(type) {
  // 以前のcorrectとwrongクラスを外す
  judgeMarkEl.classList.remove("correct", "wrong");
  // showクラスと指定された種類のクラスを追加する
  judgeMarkEl.classList.add("show", type);
}

// 判定マークを非表示にする関数
function hideJudgeMark() {
  // show・correct・wrongの各クラスをすべて外す
  judgeMarkEl.classList.remove("show", "correct", "wrong");
}

// どちらのボタンが押されたかを受け取り正誤判定する関数
function checkAnswer(index) {
  // タイマーが動いていない、または次問題待機中なら何もしない
  if (!timer || isWaitingNext) return;

  // indexに応じて押されたボタン要素を決める
  const selectedBtn = index === 0 ? btn0 : btn1;
  // 押されたボタンが正解かどうかをdatasetから判定する
  const isCorrect = selectedBtn.dataset.correct === "1";

  // 連打防止のためボタンを無効化する
  lockButtons();
  // 次の問題待機中フラグを立てる
  isWaitingNext = true;
  // 念のため既存の次問題タイマーをクリアする
  clearTimeout(nextQuizTimeout);

  // 正解した場合の処理
  if (isCorrect) {
    // スコアを1増やす
    score += 1;

    // 表示用のspan要素を新しく作る
    const item = document.createElement("span");
    // 取得アイテム用のクラス名を設定する
    item.className = "collected-item";
    // 今回正解した絵文字をspanの中身に入れる
    item.textContent = currentQuiz.emoji;
    // アイテム一覧に追加する
    itemsEl.appendChild(item);

    // 正解マークを表示する
    showJudgeMark("correct");
  } else {
    // 不正解だったボタンにwrongクラスを付ける
    selectedBtn.classList.add("wrong");
    // 不正解マークを表示する
    showJudgeMark("wrong");
  }

  // 少し待ってから次の問題へ進むタイマーを設定する
  nextQuizTimeout = setTimeout(() => {
    // すでにゲーム終了していたら何もしない
    if (!timer) return;
    // 次の問題を表示する
    nextQuiz();
  }, NEXT_WAIT);
}

// ゲーム終了時の表示更新と記録保存を行う関数
function endGame() {
  // カウントダウンタイマーを停止する
  clearInterval(timer);
  // 次の問題タイマーを停止する
  clearTimeout(nextQuizTimeout);
  // タイマーIDを空にする
  timer = null;
  // 次問題タイマーIDを空にする
  nextQuizTimeout = null;
  // 待機中フラグを解除する
  isWaitingNext = false;

  // 判定マークを隠す
  hideJudgeMark();
  // ボタン状態をリセットする
  resetButtons();

  // 新記録かどうかを入れる変数を用意する
  let isNewRecord = false;

  // 今回のスコアがハイスコアを上回ったか確認する
  if (score > highScore) {
    // ハイスコアを今回のスコアで更新する
    highScore = score;
    // ローカルストレージにも保存する
    localStorage.setItem(STORAGE_KEY, String(highScore));
    // 画面上のハイスコア表示も更新する
    highScoreEl.textContent = String(highScore);
    // 新記録フラグを立てる
    isNewRecord = true;
  }

  // 最終スコアを結果画面に表示する
  finalScoreEl.textContent = String(score);
  // ゲーム中に集めたアイテム一覧を結果画面へコピーする
  resultItemsEl.innerHTML = itemsEl.innerHTML;
  // 新記録ならメッセージを表示し、そうでなければ空文字にする
  newRecordMsgEl.textContent = isNewRecord ? "さいこうきろく👏👏" : "";

  // ゲーム画面を非表示にする
  gamePanel.style.display = "none";
  // 結果画面を表示する
  resultBox.style.display = "flex";
}