package me.coley.recaf.ui.component.panel;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;

import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;

import me.coley.recaf.asm.OpcodeUtil;
import me.coley.recaf.util.Misc;

/**
 * JPanel for tag switcher for Handle.
 * 
 * @author Matt
 */
@SuppressWarnings("serial")
public class TagTypeSwitchPanel extends JPanel implements Opcodes {
	/**
	 * Map of radio buttons to possible tags.
	 */
	private final Map<JRadioButton, Integer> compToTag = new HashMap<>();
	/**
	 * InvokeDynamic handle being modified.
	 */
	private final Handle handle;
	/**
	 * Only stored so the list can be re-painted when the tag is re-chosen.
	 */
	private final JList<AbstractInsnNode> list;
	/**
	 * Content wrapper.
	 */
	private final JPanel content = new JPanel();

	public TagTypeSwitchPanel(JList<AbstractInsnNode> list, Handle handle) {
		this.list = list;
		this.handle = handle;
		 //setMaximumSize(new Dimension(300, 300));
		// content.setMaximumSize(new Dimension(300, 300));
		// scroll.setMaximumSize(new Dimension(300, 300));
		populate(OpcodeUtil.OPS_TAG, s -> OpcodeUtil.nameToTag(s));
		setLayout(new BorderLayout());
		JScrollPane scroll = new JScrollPane(content);
		add(scroll, BorderLayout.CENTER);
	}

	private void populate(String[] tags, Function<String, Integer> getter) {
		// Set layout based on number of options
		setLayout(tags.length);
		// Add options
		for (String op : tags) {
			int value = getter.apply(op);;
			JRadioButton btn = new JRadioButton(op);
			if (value == handle.getTag()) {
				btn.setSelected(true);
			}
			btn.addActionListener(new RadioListener(btn));
			compToTag.put(btn, value);
			content.add(btn);
		}
	}

	/**
	 * Update {@link #handle} value.
	 * 
	 * @param value
	 */
	private void setValue(int value) {
		Misc.set(handle, "tag", value);
		list.repaint();
	}

	/**
	 * Sets layout depending on the content size.
	 * 
	 * @param size
	 */
	private void setLayout(int size) {
		if (size % 6 == 0 || size % 3 == 0) {
			content.setLayout(new GridLayout(0, 3));
		} else if (size % 2 == 0) {
			content.setLayout(new GridLayout(0, 2));
		} else {
			content.setLayout(new GridLayout(0, 3));
		}
	}

	/**
	 * Get the number of radio buttons.
	 * 
	 * @return
	 */
	public int getOptionCount() {
		return compToTag.keySet().size();
	}

	/**
	 * Listener for disabling other radio buttons.
	 * 
	 * @author Matt
	 */
	private class RadioListener implements ActionListener {
		private final JRadioButton btn;

		public RadioListener(JRadioButton btn) {
			this.btn = btn;
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			for (JRadioButton comp : compToTag.keySet()) {
				if (comp != btn && comp.isSelected()) {
					comp.setSelected(false);
				} else if (comp == btn) {
					setValue(compToTag.get(comp));
				}
			}
		}
	}
}

@@ -1405,16 +1405,59 @@
  300));%0A
+%09%09content.setLayout(new GridLayout(0, 2));%0A
 %09%09popula
@@ -1510,16 +1510,16 @@
 ag(s));%0A
-
 %09%09setLay
@@ -1753,34 +1753,8 @@
 ons%0A
-%09%09setLayout(tags.length);%0A
 %09%09//
@@ -2183,16 +2183,16 @@
 value);%0A
+
 %09%09list.r
@@ -2209,343 +2209,8 @@
 %09%7D%0A%0A
-%09/**%0A%09 * Sets layout depending on the content size.%0A%09 * %0A%09 * @param size%0A%09 */%0A%09private void setLayout(int size) %7B%0A%09%09if (size %25 6 == 0 %7C%7C size %25 3 == 0) %7B%0A%09%09%09content.setLayout(new GridLayout(0, 3));%0A%09%09%7D else if (size %25 2 == 0) %7B%0A%09%09%09content.setLayout(new GridLayout(0, 2));%0A%09%09%7D else %7B%0A%09%09%09content.setLayout(new GridLayout(0, 3));%0A%09%09%7D%0A%09%7D%0A%0A
 %09/**

Edit Tag-switch panel to use 2x grid always. Makes the parent panel skinnier.