package land.chipmunk.chipmunkmod.modules.custom_chat;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentBuilder;
import net.kyori.adventure.text.SelectorComponent;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.renderer.TranslatableComponentRenderer;
import org.jetbrains.annotations.NotNull;

// We don't do any translatable rendering here, but extending from that makes it easier to work with.
public final class CustomChatComponentRenderer extends TranslatableComponentRenderer<CustomChatContext> {
    @Override
    protected @NotNull Component renderSelector (final @NotNull SelectorComponent component,
                                                 final @NotNull CustomChatContext context) {
        final String pattern = component.pattern();
        if (pattern.equals("@s")) {
            final SelectorComponent.Builder builder = Component.selector()
                    .pattern(context.uuid());

            return this.mergeStyleAndOptionallyDeepRender(component, builder, context);
        }

        return super.renderSelector(component, context);
    }

    @Override
    protected @NotNull Component renderText (final @NotNull TextComponent component,
                                             final @NotNull CustomChatContext context) {
        final String content = component.content();
        if (content.equals("MESSAGE")) {
            return this.mergeMessage(component, context.message(), context);
        }

        final String arg = context.args().get(component.content());
        if (arg != null) {
            final TextComponent.Builder builder = Component.text()
                    .content(arg);

            return this.mergeStyleAndOptionallyDeepRender(component, builder, context);
        }

        return super.renderText(component, context);
    }

    @SuppressWarnings("NonExtendableApiUsage") // we're not extending it silly
    @Override
    protected <B extends ComponentBuilder<?, ?>> void mergeStyle (final Component component, final B builder,
                                                                  final CustomChatContext context) {
        super.mergeStyle(component, builder, context);

        // render clickEvent that may contain something like "MESSAGE"
        // HoverEvent already handled by super
        builder.clickEvent(this.mergeClickEvent(component.clickEvent(), context));
    }

    private Component mergeMessage (final Component root, final Component msg, final CustomChatContext context) {
        Component result = msg.applyFallbackStyle(root.style()); // applyFallbackStyle will apply everything that isn't content

        final ClickEvent clickEvent = result.clickEvent();
        if (clickEvent != null) {
            result = result.clickEvent(mergeClickEvent(clickEvent, context));
        }

        final HoverEvent<?> hoverEvent = result.hoverEvent();
        if (hoverEvent != null) {
            result = result.hoverEvent(hoverEvent.withRenderedValue(this, context));
        }

        return result;
    }

    private ClickEvent mergeClickEvent (final ClickEvent clickEvent, final CustomChatContext context) {
        if (clickEvent == null) return null;

        if (!clickEvent.action().supports(ClickEvent.Payload.string(""))) return clickEvent;

        final String value = ((ClickEvent.Payload.Text) clickEvent.payload()).value();
        final String arg = context.args().get(value);
        if (arg == null) return clickEvent;

        return switch (clickEvent.action()) {
            case OPEN_URL -> ClickEvent.openUrl(arg);
            case OPEN_FILE -> ClickEvent.openFile(arg);
            case RUN_COMMAND -> ClickEvent.runCommand(arg);
            case SUGGEST_COMMAND -> ClickEvent.suggestCommand(arg);
            case COPY_TO_CLIPBOARD -> ClickEvent.copyToClipboard(arg);
            default -> clickEvent;
        };
    }
}
