package net.minecraftforge.client.event;

import java.util.ArrayList;
import java.util.List;

import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

/**
 * Event classes for GuiScreen events.
 * 
 * @author bspkrs
 */
@SideOnly(Side.CLIENT)
public class GuiScreenEvent extends Event 
{
    /**
     * The GuiScreen object generating this event.
     */
    public final GuiScreen gui;
    
    public GuiScreenEvent(GuiScreen gui)
    {
        this.gui = gui;
    }

    public static class InitGuiEvent extends GuiScreenEvent
    {
        /**
         * The {@code buttonList} field from the GuiScreen object referenced by {@code gui}.
         */
        public List buttonList;
        
        public InitGuiEvent(GuiScreen gui, List buttonList)
        {
            super(gui);
            this.buttonList = buttonList;
        }
        
        /**
         * This event fires just after initializing {@code GuiScreen.mc}, {@code GuiScreen.fontRendererObj}, 
         * {@code GuiScreen.width}, and {@code GuiScreen.height}, and just before calling {@code GuiScreen.buttonList.clear()} 
         * and {@code GuiScreen.initGui()}. To skip or override a screen's initGui() method cancel the event.<br/><br/>
         * 
         * If canceled the following lines are skipped in {@code GuiScreen.setWorldAndResolution()}:<br/>
         * {@code this.buttonList.clear();}<br/>
         * {@code this.initGui();}<br/>
         * 
         * @author bspkrs
         */
        @Cancelable
        public static class Pre extends InitGuiEvent
        {
            public Pre(GuiScreen gui, List buttonList)
            {
                super(gui, buttonList);
            }
        }
        
        /**
         * This event fires right after {@code GuiScreen.initGui()}.
         * This is a good place to alter a GuiScreen's component layout if desired.
         * 
         * @author bspkrs
         */
        public static class Post extends InitGuiEvent
        {
            public Post(GuiScreen gui, List buttonList)
            {
                super(gui, buttonList);
            }
        }
    }
    
    public static class DrawScreenEvent extends GuiScreenEvent
    {
        /**
         * The x coordinate of the mouse pointer on the screen.
         */
        public final int mouseX;
        /**
         * The y coordinate of the mouse pointer on the screen.
         */
        public final int mouseY;
        /**
         * Partial render ticks elapsed.
         */
        public final float renderPartialTicks;

        public DrawScreenEvent(GuiScreen gui, int mouseX, int mouseY, float renderPartialTicks)
        {
            super(gui);
            this.mouseX = mouseX;
            this.mouseY = mouseY;
            this.renderPartialTicks = renderPartialTicks;
        }
        
        /**
         * This event fires just before {@code GuiScreen.drawScreen()} is called.
         * Cancel this event to skip {@code GuiScreen.drawScreen()}.
         * 
         * @author bspkrs
         */
        @Cancelable
        public static class Pre extends DrawScreenEvent
        {
            public Pre(GuiScreen gui, int mouseX, int mouseY, float renderPartialTicks)
            {
                super(gui, mouseX, mouseY, renderPartialTicks);
            }
        }

        /**
         * This event fires just after {@code GuiScreen.drawScreen()} is called.
         * 
         * @author bspkrs
         */
        public static class Post extends DrawScreenEvent
        {
            public Post(GuiScreen gui, int mouseX, int mouseY, float renderPartialTicks)
            {
                super(gui, mouseX, mouseY, renderPartialTicks);
            }
        }
    }
    
    public static class ActionPerformedEvent extends GuiScreenEvent
    {
        /**
         * The button that was clicked.
         */
        public GuiButton button;
        /**
         * A COPY of the {@code buttonList} field from the GuiScreen referenced by {@code gui}.
         */
        public List buttonList;

        public ActionPerformedEvent(GuiScreen gui, GuiButton button, List buttonList)
        {
            super(gui);
            this.button = button;
            this.buttonList = new ArrayList(buttonList);
        }
        
        /**
         * This event fires once it has been determined that a GuiButton object has been clicked.
         * Cancel this event to bypass {@code GuiScreen.actionPerformed()}.
         * Replace button with a different button from buttonList to have that button's action executed.
         * 
         * @author bspkrs
         */
        @Cancelable
        public static class Pre extends ActionPerformedEvent
        {
            public Pre(GuiScreen gui, GuiButton button, List buttonList)
            {
                super(gui, button, buttonList);
            }
        }
        
        /**
         * This event fires after {@code GuiScreen.actionPerformed()} provided that the active 
         * screen has not been changed as a result of {@code GuiScreen.actionPerformed()}.
         * 
         * @author bspkrs
         */
        public static class Post extends ActionPerformedEvent
        {
            public Post(GuiScreen gui, GuiButton button, List buttonList)
            {
                super(gui, button, buttonList);
            }
        }
    }
}