package eu.midnightdust.yaytris;

import eu.midnightdust.yaytris.game.Space;
import eu.midnightdust.yaytris.ui.ScoreMenu;
import eu.midnightdust.yaytris.ui.TetrisUI;
import eu.midnightdust.yaytris.util.SoundUtil;

import javax.swing.*;
import java.time.LocalTime;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

public class Tetris {
    public static final Random random = new Random();
    private static Space space;
    private static Timer timer;
    private static TetrisUI ui;
    private static TimerTask gravityTask;
    private static LocalTime startTime;

    public static void main(String[] args) {
        try {
            System.setProperty("java.awt.headless", "false");
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception | Error e) { System.out.printf("%s: %s\n", "Error setting system look and feel", e); }
        Settings.load();
        Translation.load(Settings.language.locale);
        HighScores.load();
        timer = new Timer("Tetris falling pieces");
        space = new Space();
        ui = new TetrisUI();
    }

    public static Space getSpace() {
        return space;
    }

    public static void resetSpace() {
        SoundUtil.stopMusic("/music/theme.wav");
        if (gravityTask != null) gravityTask.cancel();
        timer.purge();
        space = new Space();
    }

    public static void startGame() {
        SoundUtil.playMusic("/music/theme.wav", true);
        space.spawnTetromino();
        startTime = LocalTime.now();
        gravityTask = new GravityTimerTask();
        timer.scheduleAtFixedRate(gravityTask, 1, Settings.difficulty.getTimerPeriod());
    }

    public static void stopGame() {
        SoundUtil.stopMusic("/music/theme.wav");
        if (gravityTask != null) gravityTask.cancel();
        timer.purge();
        if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).gameOver();
        ui.transferFocus();
        if (HighScores.scores.values().stream().noneMatch(hs -> hs > space.getScore())) ui.showHighscoreDialog(space.getScore());
    }

    public static void updateScore(int score) {
        if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).updateScore(score);
        updateLevel(score);
    }
    public static void updateTime() {
        if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).updateTime(startTime);
    }
    public static void updateLevel(int score) {
        int newLevel = Math.max(0, (int) (score / 1000f));
        if (newLevel != space.level) {
            if (gravityTask != null && Settings.shouldScaleSpeed) {
                gravityTask.cancel();
                gravityTask = new GravityTimerTask();
                timer.scheduleAtFixedRate(gravityTask, 0, Math.max(10, Settings.difficulty.getTimerPeriod() - (Settings.difficulty.getTimerPeriod() / 8) * newLevel));
            }
            space.level = newLevel;
            if (ui.getMenuPanel() instanceof ScoreMenu) ((ScoreMenu) ui.getMenuPanel()).updateLevel(newLevel);
        }
    }

    public static class GravityTimerTask extends TimerTask {
        @Override
        public void run() {
            if (space.getCurrentTetromino() != null) {
                updateTime();
                space.getCurrentTetromino().fall();
                ui.getGamePanel().repaint();
            }
        }
    }
}
