/* 
    This file is a part of the SteamWar software.
    
    Copyright (C) 2020  SteamWar.de-Serverteam

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package de.steamwar.message;

import de.steamwar.core.BountifulWrapper;
import de.steamwar.core.Core;
import de.steamwar.sql.SteamwarUser;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;

public class Message {
    private final String resourceBundleName;
    private final ClassLoader classLoader;

    public Message(String resourceBundleName, ClassLoader classLoader){
        this.resourceBundleName = resourceBundleName;
        this.classLoader = classLoader;
    }

    /* Parsing input to a message */

    public TextComponent parseToComponent(String message, boolean prefixed, CommandSender sender, Object... params){
        return new TextComponent(TextComponent.fromLegacyText(parse(message, prefixed, sender, params)));
    }

    public String parsePrefixed(String message, CommandSender sender, Object... params){
        return parse(message, true, sender, params);
    }

    public String parse(String message, CommandSender sender, Object... params){
        return parse(message, false, sender, params);
    }

    private String parse(String message, boolean prefixed, CommandSender sender, Object... params){
        Locale locale;
        if(sender instanceof Player)
            locale = getLocale((Player) sender);
        else
            locale = Locale.getDefault();

        ResourceBundle resourceBundle = ResourceBundle.getBundle(resourceBundleName, locale, classLoader);
        String pattern = "";
        if(prefixed)
            pattern = fromRB(resourceBundle, "PREFIX") + " ";
        pattern += fromRB(resourceBundle, message);

        for (int i = 0; i < params.length; i++) {
            if (params[i] instanceof SubMessage) {
                SubMessage smsg = (SubMessage) params[i];
                params[i] = parse(smsg.getMessage(), sender, smsg.getParams());
            }
        }

        return new MessageFormat(pattern, locale).format(params);
    }

    private String fromRB(ResourceBundle bundle, String key) {
        String result = bundle.getString(key);
        if(Core.getVersion() < 12)
            result = new String(result.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
        return result;
    }

    private Locale getLocale(Player player){
        return SteamwarUser.get(player.getUniqueId()).getLocale();
    }

    /* Send a message to one player */

    public void send(String message, CommandSender sender, Object... params){
        send(message, true, sender, ChatMessageType.SYSTEM, null, null, params);
    }

    public void sendPrefixless(String message, CommandSender sender, Object... params){
        send(message, false, sender, ChatMessageType.SYSTEM, null, null, params);
    }

    public void send(String message, CommandSender sender, ChatMessageType type, Object... params){
        send(message, true, sender, type, null, null, params);
    }

    public void sendPrefixless(String message, CommandSender sender, ChatMessageType type, Object... params){
        send(message, false, sender, type, null, null, params);
    }

    public void send(String message, CommandSender sender, String onHover, ClickEvent onClick, Object... params){
        send(message, true, sender, ChatMessageType.SYSTEM, onHover, onClick, params);
    }

    public void sendPrefixless(String message, CommandSender sender, String onHover, ClickEvent onClick, Object... params){
        send(message, false, sender, ChatMessageType.SYSTEM, onHover, onClick, params);
    }

    public void send(String message, boolean prefixed, CommandSender sender, ChatMessageType type, String onHover, ClickEvent onClick, Object... params){
        TextComponent msg = parseToComponent(message, prefixed, sender, params);
        if(onHover != null)
            msg.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(onHover)));
        if(onClick != null)
            msg.setClickEvent(onClick);

        if(sender instanceof Player)
            BountifulWrapper.impl.sendMessage((Player)sender, type, msg);
        else
            sender.sendMessage(msg.toPlainText());
    }

    /* Send message to all players */

    public void broadcastPrefixless(String message, String onHover, ClickEvent onClick, Object... params){
        for(Player player : Bukkit.getOnlinePlayers())
            sendPrefixless(message, player, parse(onHover, false, player), onClick, params);
    }

    public void broadcastPrefixless(String message, Object... params){
        for(Player player : Bukkit.getOnlinePlayers())
            sendPrefixless(message, player, ChatMessageType.SYSTEM, params);
    }

    public void broadcastActionbar(String message, Object... params){
        for(Player player : Bukkit.getOnlinePlayers())
            send(message, player, ChatMessageType.ACTION_BAR, params);
    }

    public void broadcast(String message, String onHover, ClickEvent onClick, Object... params){
        for(Player player : Bukkit.getOnlinePlayers())
            send(message, player, parse(onHover, false, player), onClick, params);
    }

    public void broadcast(String message, Object... params){
        for(Player player : Bukkit.getOnlinePlayers())
            send(message, player, ChatMessageType.SYSTEM, params);
    }

    public void chat(String message, Object... params){
        for(Player player : Bukkit.getOnlinePlayers())
            sendPrefixless(message, player, ChatMessageType.CHAT, params);
    }
}
