import java.awt.*; // Import the java.awt package for working with the GUI
import java.awt.event.*; // Import the java.awt.event package for working with GUI events
import javax.swing.*; // Import the javax.swing package for working with Swing components
import javax.swing.event.ChangeEvent; // Import the javax.swing.event package for working with ChangeEvents
import javax.swing.event.ChangeListener; // Import the ChangeListener interface
import java.util.Random; // Import the Random class for generating random numbers

public class Main {
    static JFrame frame = new JFrame("Attack Roller");
    static JFrame output = new JFrame("Output");

    // Create a JTextArea for displaying the output
    static JTextArea outputTextArea = new JTextArea();
    // Declare JSlider fields for the different damage types
    public static JSlider slashingDamageSlider = new JSlider(1, 4, 2);
    public static JSlider forceDamageSlider = new JSlider(1, 4, 2);
    public static JSlider fireDamageSlider = new JSlider(1, 4, 2);
    public static JSlider radiantDamageSlider = new JSlider(1, 4, 2);
    public static JSlider lightningDamageSlider = new JSlider(1, 4, 2);
    public static JSlider thunderDamageSlider = new JSlider(1, 4, 2);
    public static JSlider poisonDamageSlider = new JSlider(1, 4, 2);
    public static void main(String[] args) {
        // Create a new JFrame with the title "Attack Roller"
        frame.setSize(400, 300); // Set the size of the frame
        frame.setLayout(new GridLayout(0, 3));  // Use a GridLayout to arrange components in rows and columns

        // Create output window
        output.setSize(500, 800);
        output.setLayout(new BorderLayout());  // Use a GridLayout to arrange components in rows and columns


        // Create a scroll pane for the text area and add it to the output frame
        JScrollPane scrollPane = new JScrollPane(outputTextArea);
        output.add(scrollPane, BorderLayout.CENTER);

        outputTextArea.setEditable(false);

        JButton clearTextButton = new JButton("Clear Text");
        clearTextButton.setPreferredSize(new Dimension(100, 20));  // Set the preferred size of the button
        clearTextButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                outputTextArea.setText("");
            }
        });
        output.add(clearTextButton, BorderLayout.SOUTH);

        // Add number of attacks slider and label
        JSlider attackSlider = new JSlider(1, 16, 4); // Create a JSlider for the number of attacks with a range of 1-12 and an initial value of 4
        JLabel numAttacksLabel = new JLabel(String.valueOf(attackSlider.getValue())); // Create a JLabel for displaying the number of attacks, with an initial value from the attackSlider
        attackSlider.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                numAttacksLabel.setText(String.valueOf(attackSlider.getValue())); // When the attackSlider value changes, update the numAttacksLabel with the new value
            }
        });
        frame.add(new JLabel("Number of attacks:")); // Add a label for the number of attacks
        frame.add(attackSlider); // Add the attackSlider
        frame.add(numAttacksLabel); // Add the numAttacksLabel

        // Add armor class slider and label
        JSlider armorClassSlider = new JSlider(1, 40, 20);
        JLabel armorClassLabel = new JLabel(String.valueOf(armorClassSlider.getValue()));
        armorClassSlider.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                armorClassLabel.setText(String.valueOf(armorClassSlider.getValue()));
            }
        });
        frame.add(new JLabel("Armor class:"));
        frame.add(armorClassSlider);
        frame.add(armorClassLabel);

        // Add damage type sliders and labels
        addDamageTypeSlider(frame, "Slashing Damage:", slashingDamageSlider);
        addDamageTypeSlider(frame, "Force Damage:", forceDamageSlider);
        addDamageTypeSlider(frame, "Fire Damage:", fireDamageSlider);
        addDamageTypeSlider(frame, "Radiant Damage:", radiantDamageSlider);
        addDamageTypeSlider(frame, "Lightning Damage:", lightningDamageSlider);
        addDamageTypeSlider(frame, "Thunder Damage:", thunderDamageSlider);
        addDamageTypeSlider(frame, "Poison Damage:", poisonDamageSlider);

        JButton rollButton = new JButton("Roll Attack");
        rollButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Random random = new Random();
                int numRolls = attackSlider.getValue();
                int armorClass = armorClassSlider.getValue();
                int attackBonus = 17;
                int successfulAttacks = 0;
                outputTextArea.append("Attacks:\n");
                for (int i = 0; i < numRolls; i++) {
                    int roll = random.nextInt(20) + 1;
                    int attack = roll + attackBonus;
                    if(roll == 20) {
                        successfulAttacks += 2;
                    } else if(attack >= armorClass) {
                        successfulAttacks ++;
                    }
                    // Append the details of the attack to the output window
                    outputTextArea.append("Attack " + (i+1) + ": roll=" + roll + ", bonus=" + attackBonus + ", AC=" + armorClass + " => " + (roll == 20 ? "CRITICAL HIT" : (attack >= armorClass ? "HIT" : "MISS")) + "\n");
                }
                outputTextArea.append("Successful Attacks: " + successfulAttacks + "\n");
                int totalDamage = 0;
                for (int i = 1; i <= successfulAttacks; i++) {
                    outputTextArea.append("Attack " + i + ")\n");
                    int damage = getDamage();
                    outputTextArea.append("damage: " + damage + "\n");
                    totalDamage += damage;
                }
                outputTextArea.append("Total Attack Damage: " + totalDamage + "\n");
                output.setVisible(true);
            }
        });
        frame.add(rollButton);

        frame.setVisible(true);
    }

    public static void addDamageTypeSlider(JFrame frame, String name, JSlider slider) {
        JLabel label = new JLabel("Normal");
        slider.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                int value = slider.getValue();
                if(value == 1) {
                    label.setText("Vulnerable");
                } else if(value == 2) {
                    label.setText("Normal");
                } else if(value == 3) {
                    label.setText("Resistant");
                } else if(value == 4) {
                    label.setText("Immune");
                }
            }
        });
        frame.add(new JLabel(name));
        frame.add(slider);
        frame.add(label);
    }

    public static int getDamage() {
        int damage = 0;

        // Calculate slashing damage
        double slashingRoll = (rollDamageDie(10)+11);
        double slashing = Math.floor(slashingRoll * getMultiplier(slashingDamageSlider.getValue()));
        outputTextArea.append("- Slashing: " + slashingRoll + "=" + slashing + "\n");
        damage += slashing;

        // Calculate force damage
        double forceRoll = (rollDamageDie(4)+3);
        double force = Math.floor(forceRoll * getMultiplier(forceDamageSlider.getValue()));
        outputTextArea.append("- Force: " + forceRoll + "=" + force + "\n");
        damage += force;

        // Calculate fire damage
        double fireRoll = (rollDamageDie(4)+3);
        double fire = Math.floor(fireRoll * getMultiplier(fireDamageSlider.getValue()));
        outputTextArea.append("- Fire: " + fireRoll + "=" + fire + "\n");
        damage += fire;

        // Calculate radiant damage
        double radiantRoll = (rollDamageDie(4)+3);
        double radiant = Math.floor(radiantRoll * getMultiplier(radiantDamageSlider.getValue()));
        outputTextArea.append("- Radiant: " + radiantRoll + "=" + radiant + "\n");
        damage += radiant;

        // Calculate lightning damage
        double lightningRoll = (rollDamageDie(4)+3);
        double lightning = Math.floor(lightningRoll * getMultiplier(lightningDamageSlider.getValue()));
        outputTextArea.append("- Lightning: " + lightningRoll + "=" + lightning + "\n");
        damage += lightning;

        // Calculate thunder damage
        double thunderRoll = (rollDamageDie(4)+3);
        double thunder = Math.floor(thunderRoll * getMultiplier(thunderDamageSlider.getValue()));
        outputTextArea.append("- Thunder: " + thunderRoll + "=" + thunder + "\n");
        damage += thunder;

        // Calculate poison damage
        double poisonRoll = (rollDamageDie(4)+3);
        double poison = Math.floor(poisonRoll * getMultiplier(poisonDamageSlider.getValue()));
        outputTextArea.append("- Poison: " + poisonRoll + "=" + poison + "\n");
        damage += poison;

        return damage;
    }

    public static int rollDamageDie(int sides) {
        Random random = new Random();
        int dice = random.nextInt(sides) + 1;
        if(dice <= 2) {
            dice = random.nextInt(sides) + 1;
        }
        return dice;
    }

    public static double getMultiplier(int damageType) {
        switch (damageType) {
            case 1:
                return 2;
            case 3:
                return 0.5;
            case 4:
                return 0;
            default:
                return 1;
        }
    }
}