package eu.mrneznamy.mrultimatelibrary.title;

import eu.mrneznamy.mrultimatelibrary.scheduler.MrLibScheduler;
import eu.mrneznamy.mrultimatelibrary.utils.MrLibColors;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;

/**
 * Title display system with multiple modes
 */
public class MrLibTitle {
    
    private final JavaPlugin plugin;
    private final Map<UUID, TitleTask> activeTitles = new HashMap<>();
    
    public MrLibTitle(JavaPlugin plugin) {
        this.plugin = plugin;
    }
    
    /**
     * Show simple title
     * 
     * @param player Player
     * @param title Title text
     * @param subtitle Subtitle text
     * @param fadeIn Fade in time (ticks)
     * @param stay Stay time (ticks)
     * @param fadeOut Fade out time (ticks)
     */
    public void show(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut) {
        clearTitle(player);
        
        player.sendTitle(
            MrLibColors.colorize(title, player),
            MrLibColors.colorize(subtitle, player),
            fadeIn, stay, fadeOut
        );
    }
    
    /**
     * Show repeating title (updates every interval)
     * 
     * @param player Player
     * @param titleProvider Title provider
     * @param subtitleProvider Subtitle provider
     * @param intervalTicks Update interval
     * @param durationTicks Total duration
     */
    public void showRepeating(Player player, 
                              Function<Player, String> titleProvider,
                              Function<Player, String> subtitleProvider,
                              long intervalTicks, 
                              long durationTicks) {
        clearTitle(player);
        
        TitleTask task = new TitleTask(player, titleProvider, subtitleProvider, intervalTicks, durationTicks);
        activeTitles.put(player.getUniqueId(), task);
        task.start(plugin);
    }
    
    /**
     * Show countdown title
     * 
     * @param player Player
     * @param titleFormat Title (use %time% for seconds)
     * @param subtitle Subtitle
     * @param seconds Countdown seconds
     */
    public void showCountdown(Player player, String titleFormat, String subtitle, int seconds) {
        clearTitle(player);
        
        final int[] remaining = {seconds};
        
        TitleTask task = new TitleTask(
            player,
            p -> titleFormat.replace("%time%", String.valueOf(remaining[0])),
            p -> subtitle,
            20L,  
            seconds * 20L
        );
        
        task.onTick = () -> remaining[0]--;
        activeTitles.put(player.getUniqueId(), task);
        task.start(plugin);
    }
    
    /**
     * Show sequence of titles
     * 
     * @param player Player
     * @param sequences Array of title sequences
     */
    public void showSequence(Player player, TitleSequence... sequences) {
        clearTitle(player);
        showNextSequence(player, sequences, 0);
    }
    
    private void showNextSequence(Player player, TitleSequence[] sequences, int index) {
        if (index >= sequences.length || !player.isOnline()) {
            return;
        }
        
        TitleSequence seq = sequences[index];
        show(player, seq.title, seq.subtitle, seq.fadeIn, seq.stay, seq.fadeOut);
        
        
        if (index + 1 < sequences.length) {
            long delay = seq.fadeIn + seq.stay + seq.fadeOut;
            MrLibScheduler.runTaskLater(plugin, () -> {
                showNextSequence(player, sequences, index + 1);
            }, delay);
        }
    }
    
    /**
     * Clear title for player
     */
    public void clearTitle(Player player) {
        TitleTask task = activeTitles.remove(player.getUniqueId());
        if (task != null) {
            task.cancel();
        }
        player.resetTitle();
    }
    
    /**
     * Clear all titles
     */
    public void clearAll() {
        activeTitles.values().forEach(TitleTask::cancel);
        activeTitles.clear();
    }
    
    /**
     * Title task for repeating/countdown titles
     */
    private class TitleTask implements Runnable {
        private final Player player;
        private final Function<Player, String> titleProvider;
        private final Function<Player, String> subtitleProvider;
        private final long intervalTicks;
        private long remainingTicks;
        private MrLibScheduler.MrLibTask task;
        private Runnable onTick;
        
        public TitleTask(Player player, 
                         Function<Player, String> titleProvider,
                         Function<Player, String> subtitleProvider,
                         long intervalTicks,
                         long durationTicks) {
            this.player = player;
            this.titleProvider = titleProvider;
            this.subtitleProvider = subtitleProvider;
            this.intervalTicks = intervalTicks;
            this.remainingTicks = durationTicks;
        }
        
        public void start(JavaPlugin plugin) {
            task = MrLibScheduler.runTaskTimer(plugin, this, 0L, intervalTicks);
        }
        
        @Override
        public void run() {
            if (!player.isOnline() || remainingTicks <= 0) {
                cancel();
                activeTitles.remove(player.getUniqueId());
                return;
            }
            
            String title = titleProvider.apply(player);
            String subtitle = subtitleProvider != null ? subtitleProvider.apply(player) : "";
            
            player.sendTitle(
                MrLibColors.colorize(title, player),
                MrLibColors.colorize(subtitle, player),
                5, (int)intervalTicks, 5
            );
            
            if (onTick != null) {
                onTick.run();
            }
            
            remainingTicks -= intervalTicks;
        }
        
        public void cancel() {
            if (task != null) {
                task.cancel();
            }
        }
    }
    
    /**
     * Title sequence for animations
     */
    public static class TitleSequence {
        String title;
        String subtitle;
        int fadeIn;
        int stay;
        int fadeOut;
        
        public TitleSequence(String title, String subtitle, int fadeIn, int stay, int fadeOut) {
            this.title = title;
            this.subtitle = subtitle;
            this.fadeIn = fadeIn;
            this.stay = stay;
            this.fadeOut = fadeOut;
        }
        
        public static TitleSequence of(String title, String subtitle) {
            return new TitleSequence(title, subtitle, 10, 70, 20);
        }
    }
}

