// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.groovy.swingBuilder;

import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.psi.*;
import com.intellij.psi.scope.ElementClassHint;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor;
import org.jetbrains.plugins.groovy.extensions.impl.TypeCondition;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierFlags;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrMethodWrapper;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public final class SwingBuilderNonCodeMemberContributor extends NonCodeMembersContributor {

  private static final Key<MultiMap<String, PsiMethod>> KEY = Key.create("SwingBuilderNonCodeMemberContributor.KEY");

  private static final @NonNls Object METHOD_KIND = "SwingBuilder_builder_method";

  private static final class MyBuilder {
    private final PsiManager myManager;
    private final MultiMap<String, PsiMethod> myResult = new MultiMap<>();
    private final GlobalSearchScope myResolveScope;
    private final PsiElementFactory myFactory;
    private final PsiClass mySwingBuilderClass;
    private final PsiType MANY_OBJECTS;

    private final Map<String, PsiType> myTypeMap = new HashMap<>();

    private MyBuilder(PsiClass swingBuilderClass) {
      myManager = swingBuilderClass.getManager();
      mySwingBuilderClass = swingBuilderClass;
      myResolveScope = swingBuilderClass.getResolveScope();
      myFactory = JavaPsiFacade.getElementFactory(myManager.getProject());
      MANY_OBJECTS = new PsiEllipsisType(type(CommonClassNames.JAVA_LANG_OBJECT));
    }

    public static class MyMethodBuilder extends GrLightMethodBuilder {
      private String myNavigationClass;

      public MyMethodBuilder(PsiManager manager, String name) {
        super(manager, name);
        setMethodKind(METHOD_KIND);
        setOriginInfo("SwingBuilder method");
      }

      @Override
      public @NotNull PsiElement getNavigationElement() {
        PsiElement res = super.getNavigationElement();
        if (res != this || myNavigationClass == null) return res;

        PsiClass aClass = JavaPsiFacade.getInstance(getProject()).findClass(myNavigationClass, getResolveScope());
        if (aClass == null) return res;

        PsiMethod[] methods = aClass.findMethodsByName("newInstance", false);
        if (methods.length != 1) return aClass;

        return methods[0];
      }

      public void setNavigationClass(String navigationClass) {
        myNavigationClass = navigationClass;
      }
    }

    private @NotNull PsiType type(@NotNull String typeName) {
      PsiType res = myTypeMap.get(typeName);
      if (res == null) {
        res = myFactory.createTypeByFQClassName(typeName, myResolveScope);
        myTypeMap.put(typeName, res);
      }
      return res;
    }

    private void add(@NotNull PsiMethod method) {
      myResult.putValue(method.getName(), method);
    }

    private MyMethodBuilder method(String name, String returnType, @Nullable String navigationClass) {
      MyMethodBuilder res = new MyMethodBuilder(myManager, name);
      res.setModifiers(GrModifierFlags.PUBLIC_MASK);
      res.setReturnType(type(returnType));
      res.setContainingClass(mySwingBuilderClass);
      if (navigationClass != null) {
        assert navigationClass.startsWith("groovy.swing."); // NON-NLS
        res.setNavigationClass(navigationClass);
      }
      return res;
    }

    private void methodObject(@NlsSafe String name, String returnType, @Nullable String navigationClass) {
      methodObject(name, returnType, navigationClass, null);
    }

    private void methodObject(@NlsSafe String name, @NlsSafe String returnType, @Nullable String navigationClass,
                              @Nullable Map<@NlsSafe String, NamedArgumentDescriptor> namedArg) {
      MyMethodBuilder method = method(name, returnType, navigationClass);
      method.addParameter("map", type(CommonClassNames.JAVA_UTIL_MAP), true);
      method.addParameter("params", MANY_OBJECTS);
      if (namedArg != null) {
        method.setNamedParameters(namedArg);
      }
      add(method);
    }

    //private MyMethodBuilder methodWithAttr(String name, String returnType, @Nullable String navigationClass) {
    //  return method(name, returnType, navigationClass).addParameter("attr", CommonClassNames.JAVA_UTIL_MAP, true);
    //}

    //private MyMethodBuilder method(String name, String returnType, @Nullable String navigationClass, String paramName, @Nullable String paramType, boolean isOptional) {
    //  MyMethodBuilder res = methodWithAttr(name, returnType, navigationClass);
    //  res.addParameter(paramName, paramType == null ? returnType : paramType, isOptional);
    //  res.addClosureParam();
    //
    //  return res;
    //}

    //private void beanFactory(@Nullable String factoryName, String name, String returnType, boolean parameterOptional) {
    //  add(method(name, returnType, factoryName, "value", CommonClassNames.JAVA_LANG_STRING, false));
    //  add(method(name, returnType, factoryName,"value", returnType, parameterOptional));
    //}

    //private MyMethodBuilder acceptAllMethod(String name, String returnType, @Nullable String navigationClass) {
    //  return acceptAllMethodLeaf(name, returnType, navigationClass).addClosureParam();
    //}

    //private MyMethodBuilder acceptAllMethodLeaf(String name, String returnType, @Nullable String navigationClass) {
    //  return methodWithAttr(name, returnType, navigationClass).addParameter("value", CommonClassNames.JAVA_LANG_OBJECT, true);
    //}

    private void registerExplicitMethod(String name, String realMethodName) {
      for (PsiMethod method : mySwingBuilderClass.findMethodsByName(realMethodName, false)) {
        add(GrMethodWrapper.wrap(method));
      }
    }

    private void generateMethods() {
      // registerSupportNodes()
      methodObject("action", "javax.swing.Action", "groovy.swing.factory.ActionFactory");

      methodObject("actions", CommonClassNames.JAVA_UTIL_LIST, "groovy.swing.factory.CollectionFactory");

      methodObject("map", CommonClassNames.JAVA_UTIL_MAP, "groovy.swing.factory.MapFactory");

      methodObject("imageIcon", "javax.swing.ImageIcon", "groovy.swing.factory.ImageIconFactory",
                   Map.of(
                     "image", new TypeCondition(type("java.awt.Image")),
                     "url", new TypeCondition(type("java.net.URL")),
                     "file", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "resource", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "class", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "description", NamedArgumentDescriptor.TYPE_STRING));

      methodObject("buttonGroup", "javax.swing.BoxLayout", "groovy.swing.factory.ButtonGroupFactory");

      methodObject("noparent", CommonClassNames.JAVA_UTIL_LIST, "groovy.swing.factory.CollectionFactory");

      registerExplicitMethod("keyStrokeAction", "createKeyStrokeAction");
      //registerExplicitMethod("shortcut", "shortcut");

      // registerBinding()
      methodObject("bind", "org.codehaus.groovy.binding.FullBinding", "groovy.swing.factory.BindFactory",
                    Map.ofEntries(
                     Map.entry("source", NamedArgumentDescriptor.SIMPLE_ON_TOP),
                     Map.entry("target", NamedArgumentDescriptor.SIMPLE_ON_TOP),
                     Map.entry("update", NamedArgumentDescriptor.SIMPLE_ON_TOP),
                     Map.entry("targetProperty", NamedArgumentDescriptor.TYPE_STRING),
                     Map.entry("mutual", NamedArgumentDescriptor.SIMPLE_ON_TOP),
                     Map.entry("sourceEvent", NamedArgumentDescriptor.TYPE_STRING),
                     Map.entry("sourceValue", NamedArgumentDescriptor.TYPE_CLOSURE),
                     Map.entry("sourceProperty", NamedArgumentDescriptor.TYPE_STRING),
                     Map.entry("value", NamedArgumentDescriptor.SIMPLE_ON_TOP),
                     Map.entry("bind", NamedArgumentDescriptor.SIMPLE_ON_TOP),
                     Map.entry("group", NamedArgumentDescriptor.SIMPLE_ON_TOP)));

      methodObject("bindProxy", "org.codehaus.groovy.binding.BindingProxy", "groovy.swing.factory.BindProxyFactory",
                   Map.of("bind", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      methodObject("bindGroup", "org.codehaus.groovy.binding.AggregateBinding", "groovy.swing.factory.BindGroupFactory",
                   Map.of("bind", NamedArgumentDescriptor.SIMPLE_ON_TOP));


      // registerPassThruNodes()
      methodObject("widget", "java.awt.Component", "groovy.swing.factory.WidgetFactory", Map
        .of("widget", new TypeCondition(type("java.awt.Component"))));

      methodObject("container", "java.awt.Component", "groovy.swing.factory.WidgetFactory", Map
        .of("container", new TypeCondition(type("java.awt.Component"))));

      methodObject("bean", CommonClassNames.JAVA_LANG_OBJECT, "groovy.swing.factory.WidgetFactory",
                   Map.of("bean", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      // registerWindows()
      methodObject("dialog", "javax.swing.JDialog", "groovy.swing.factory.DialogFactory",
                   Map.of("owner", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                          "defaultButtonProperty", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                          "pack", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                          "show", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      methodObject("fileChooser", "javax.swing.JFileChooser", null);

      methodObject("frame", "javax.swing.JFrame", "groovy.swing.factory.FrameFactory", Map
        .of("pack", NamedArgumentDescriptor.SIMPLE_ON_TOP, "show", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      methodObject("optionPane", "javax.swing.JOptionPane", null);

      methodObject("window", "javax.swing.JWindow", "groovy.swing.factory.WindowFactory",
                   Map.of("pack", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                          "show", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                          "owner", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      // registerActionButtonWidgets()
      methodObject("button", "javax.swing.JButton", "groovy.swing.factory.RichActionWidgetFactory");
      methodObject("checkBox", "javax.swing.JCheckBox", "groovy.swing.factory.RichActionWidgetFactory");
      methodObject("checkBoxMenuItem", "javax.swing.JCheckBoxMenuItem", "groovy.swing.factory.RichActionWidgetFactory");
      methodObject("menuItem", "javax.swing.JMenuItem", "groovy.swing.factory.RichActionWidgetFactory");
      methodObject("radioButton", "javax.swing.JRadioButton", "groovy.swing.factory.RichActionWidgetFactory");
      methodObject("radioButtonMenuItem", "javax.swing.JRadioButtonMenuItem", "groovy.swing.factory.RichActionWidgetFactory");
      methodObject("toggleButton", "javax.swing.JToggleButton", "groovy.swing.factory.RichActionWidgetFactory");

      // registerTextWidgets()
      methodObject("editorPane", "javax.swing.JEditorPane", "groovy.swing.factory.TextArgWidgetFactory");
      methodObject("label", "javax.swing.JLabel", "groovy.swing.factory.TextArgWidgetFactory");
      methodObject("passwordField", "javax.swing.JPasswordField", "groovy.swing.factory.TextArgWidgetFactory");
      methodObject("textArea", "javax.swing.JTextArea", "groovy.swing.factory.TextArgWidgetFactory");
      methodObject("textField", "javax.swing.JTextField", "groovy.swing.factory.TextArgWidgetFactory");
      methodObject("textPane", "javax.swing.JTextPane", "groovy.swing.factory.TextArgWidgetFactory");
      methodObject("formattedTextField", "javax.swing.JFormattedTextField", "groovy.swing.factory.FormattedTextFactory",
                   Map.of(
                     "format", new TypeCondition(type("java.text.Format")),
                     "value", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      // registerMDIWidgets()
      methodObject("desktopPane", "javax.swing.JDesktopPane", null);
      methodObject("internalFrame", "javax.swing.JInternalFrame", "groovy.swing.factory.InternalFrameFactory");

      // registerBasicWidgets()
      methodObject("colorChooser", "javax.swing.JColorChooser", null);
      methodObject("comboBox", "javax.swing.JComboBox", "groovy.swing.factory.ComboBoxFactory",
                   Map.of("items", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      methodObject("list", "javax.swing.JList", "groovy.swing.factory.ListFactory",
                   Map.of("items", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      methodObject("progressBar", "javax.swing.JProgressBar", null);
      methodObject("separator", "javax.swing.JSeparator", "groovy.swing.factory.SeparatorFactory");
      methodObject("scrollBar", "javax.swing.JScrollBar", null);
      methodObject("slider", "javax.swing.JSlider", null);
      methodObject("spinner", "javax.swing.JSpinner", null);
      methodObject("tree", "javax.swing.JTree", null);

      //registerMenuWidgets()
      methodObject("menu", "javax.swing.JMenu", null);
      methodObject("menuBar", "javax.swing.JMenuBar", null);
      methodObject("popupMenu", "javax.swing.JPopupMenu", null);

      // registerContainers()
      methodObject("panel", "javax.swing.JPanel", null);
      methodObject("scrollPane", "javax.swing.JScrollPane", "groovy.swing.factory.ScrollPaneFactory");
      methodObject("splitPane", "javax.swing.JSplitPane", "groovy.swing.factory.SplitPaneFactory");
      methodObject("tabbedPane", "javax.swing.JTabbedPane", "groovy.swing.factory.TabbedPaneFactory");

      methodObject("toolBar", "javax.swing.JToolBar", null);
      methodObject("viewport", "javax.swing.JViewport", null);
      methodObject("layeredPane", "javax.swing.JLayeredPane", null);

      // registerDataModels()
      methodObject("boundedRangeModel", "javax.swing.DefaultBoundedRangeModel", null);
      methodObject("spinnerDateModel", "javax.swing.SpinnerDateModel", null);
      methodObject("spinnerListModel", "javax.swing.SpinnerListModel", null);
      methodObject("spinnerNumberModel", "javax.swing.SpinnerNumberModel", null);

      // registerTableComponents()
      methodObject("table", "javax.swing.JTable", "groovy.swing.factory.TableFactory");
      methodObject("tableColumn", "javax.swing.table.TableColumn", null);
      methodObject("tableModel", "javax.swing.table.TableModel", "groovy.swing.factory.TableModelFactory",
                   Map.of(
                     "tableModel", new TypeCondition(type("javax.swing.table.TableModel")),
                     "model", new TypeCondition(type("groovy.model.ValueModel")),
                     "list", NamedArgumentDescriptor.SIMPLE_ON_TOP
                   ));

      methodObject("propertyColumn", "javax.swing.table.TableColumn", "groovy.swing.factory.PropertyColumnFactory",
                   Map.of(
                     "propertyName", NamedArgumentDescriptor.TYPE_STRING,
                     "header", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "type", new TypeCondition(type(CommonClassNames.JAVA_LANG_CLASS)),
                     "editable", NamedArgumentDescriptor.SIMPLE_ON_TOP
                   ));

      methodObject("closureColumn", "javax.swing.table.TableColumn", "groovy.swing.factory.ClosureColumnFactory",
                   Map.of(
                     "header", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "read", new TypeCondition(type(GroovyCommonClassNames.GROOVY_LANG_CLOSURE)),
                     "write", new TypeCondition(type(GroovyCommonClassNames.GROOVY_LANG_CLOSURE)),
                     "type", new TypeCondition(type(CommonClassNames.JAVA_LANG_CLASS))
                   ));

      methodObject("columnModel", "javax.swing.table.TableColumnModel", "groovy.swing.factory.ColumnModelFactory");

      methodObject("column", "javax.swing.table.TableColumn", "groovy.swing.factory.ColumnFactory",
                   Map.of("width", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      // registerBasicLayouts()
      methodObject("borderLayout", "java.awt.BorderLayout", "groovy.swing.factory.LayoutFactory");
      methodObject("cardLayout", "java.awt.CardLayout", "groovy.swing.factory.LayoutFactory");
      methodObject("flowLayout", "java.awt.FlowLayout", "groovy.swing.factory.LayoutFactory");
      methodObject("gridLayout", "java.awt.GridLayout", "groovy.swing.factory.LayoutFactory");
      methodObject("overlayLayout", "javax.swing.OverlayLayout", "groovy.swing.factory.LayoutFactory");
      methodObject("springLayout", "javax.swing.SpringLayout", "groovy.swing.factory.LayoutFactory");
      methodObject("gridBagLayout", "java.awt.GridBagLayout", "groovy.swing.factory.LayoutFactory");
      methodObject("gridBagConstraints", "java.awt.GridBagConstraints", "groovy.swing.factory.LayoutFactory");
      methodObject("gbc", "java.awt.GridBagConstraints", "groovy.swing.factory.LayoutFactory");

      // registerBoxLayout()
      methodObject("boxLayout", "javax.swing.BoxLayout", "groovy.swing.factory.BoxLayoutFactory",
                   Map.of("axis", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      methodObject("box", "javax.swing.Box", "groovy.swing.factory.BoxFactory", Map.of(
        "axis", new TypeCondition(type("java.lang.Number"))));

      methodObject("hbox", "javax.swing.Box", "groovy.swing.factory.HBoxFactory");
      methodObject("hglue", "java.awt.Component", "groovy.swing.factory.HGlueFactory");
      methodObject("hstrut", "java.awt.Component", "groovy.swing.factory.HStrutFactory", Map.of(
        "width", new TypeCondition(type("java.lang.Number"))));

      methodObject("vbox", "javax.swing.Box", "groovy.swing.factory.VBoxFactory");
      methodObject("vglue", "java.awt.Component", "groovy.swing.factory.VGlueFactory");
      methodObject("vstrut", "java.awt.Component", "groovy.swing.factory.VStrutFactory", Map.of(
        "height", new TypeCondition(type("java.lang.Number"))));

      methodObject("glue", "java.awt.Component", "groovy.swing.factory.GlueFactory");
      methodObject("rigidArea", "java.awt.Component", "groovy.swing.factory.RigidAreaFactory",
                   Map.of(
                     "size", new TypeCondition(type("java.awt.Dimension")),
                     "height", new TypeCondition(type("java.lang.Number")),
                     "width", new TypeCondition(type("java.lang.Number"))
                   ));

      // registerTableLayout()
      methodObject("tableLayout", "groovy.swing.impl.TableLayout", "groovy.swing.factory.TableLayoutFactory");
      methodObject("tr", "groovy.swing.impl.TableLayoutRow", "groovy.swing.factory.TRFactory");
      methodObject("td", "groovy.swing.impl.TableLayoutCell", "groovy.swing.factory.TDFactory");

      // registerBorders()
      methodObject("lineBorder", "javax.swing.border.LineBorder", "groovy.swing.factory.LineBorderFactory",
                   Map.of(
                     "parent", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "color", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "thickness", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "roundedCorners", NamedArgumentDescriptor.SIMPLE_ON_TOP
                   ));

      NamedArgumentDescriptor namedArgColor = new TypeCondition(type("java.awt.Color"));

      Map<@NlsSafe String, NamedArgumentDescriptor> m = Map.of(
        "parent", NamedArgumentDescriptor.SIMPLE_ON_TOP,
        "highlight", namedArgColor,
        "shadow", namedArgColor,
        "highlightOuter", namedArgColor,
        "highlightInner", namedArgColor,
        "shadowOuter", namedArgColor,
        "shadowInner", namedArgColor);

      methodObject("loweredBevelBorder", "javax.swing.border.Border", "groovy.swing.factory.BevelBorderFactory", m);
      methodObject("raisedBevelBorder", "javax.swing.border.Border", "groovy.swing.factory.BevelBorderFactory", m);

      m = Map.of(
        "parent", NamedArgumentDescriptor.SIMPLE_ON_TOP,
        "highlight", namedArgColor,
        "shadow", namedArgColor);

      methodObject("etchedBorder", "javax.swing.border.Border", "groovy.swing.factory.EtchedBorderFactory", m);
      methodObject("loweredEtchedBorder", "javax.swing.border.Border", "groovy.swing.factory.EtchedBorderFactory", m);
      methodObject("raisedEtchedBorder", "javax.swing.border.Border", "groovy.swing.factory.EtchedBorderFactory", m);

      methodObject("titledBorder", "javax.swing.border.TitledBorder", "groovy.swing.factory.TitledBorderFactory",
                   Map.of(
                     "parent", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "title", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "position", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "justification", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "border", new TypeCondition(type("javax.swing.border.Border")),
                     "color", namedArgColor,
                     "font", new TypeCondition(type("java.awt.Font"))));

      methodObject("emptyBorder", "javax.swing.border.Border", "groovy.swing.factory.EmptyBorderFactory");
      methodObject("emptyBorder", "javax.swing.border.Border", "groovy.swing.factory.EmptyBorderFactory");
      methodObject("emptyBorder", "javax.swing.border.Border", "groovy.swing.factory.EmptyBorderFactory", Map.of(
        "parent", NamedArgumentDescriptor.SIMPLE_ON_TOP,
        "top", NamedArgumentDescriptor.TYPE_INTEGER,
        "left", NamedArgumentDescriptor.TYPE_INTEGER,
        "bottom", NamedArgumentDescriptor.TYPE_INTEGER,
        "right", NamedArgumentDescriptor.TYPE_INTEGER
      ));

      methodObject("compoundBorder", "javax.swing.border.CompoundBorder", "groovy.swing.factory.CompoundBorderFactory", Map.of(
        "parent", NamedArgumentDescriptor.SIMPLE_ON_TOP,
        "inner", new TypeCondition(type("javax.swing.border.Border")),
        "outer", new TypeCondition(type("javax.swing.border.Border"))
      ));

      methodObject("matteBorder", "javax.swing.border.Border", "groovy.swing.factory.MatteBorderFactory",
                   Map.of(
                     "parent", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "icon", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "color", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "size", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "top", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "left", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "bottom", NamedArgumentDescriptor.SIMPLE_ON_TOP,
                     "right", NamedArgumentDescriptor.SIMPLE_ON_TOP));

      // registerRenderers()
      methodObject("tableCellRenderer", "groovy.swing.impl.ClosureRenderer", "groovy.swing.factory.RendererFactory");
      methodObject("listCellRenderer", "groovy.swing.impl.ClosureRenderer", "groovy.swing.factory.RendererFactory");
      methodObject("cellRenderer", "groovy.swing.impl.ClosureRenderer", "groovy.swing.factory.RendererFactory");
      methodObject("headerRenderer", "groovy.swing.impl.ClosureRenderer", "groovy.swing.factory.RendererFactory");
      methodObject("onRender", CommonClassNames.JAVA_UTIL_MAP, "groovy.swing.factory.RendererUpdateFactory");

      // registerEditors()
      methodObject("cellEditor", "groovy.swing.impl.ClosureCellEditor", "groovy.swing.factory.CellEditorFactory");
      methodObject("editorValue", CommonClassNames.JAVA_UTIL_MAP, "groovy.swing.factory.CellEditorGetValueFactory");
      methodObject("prepareEditor", CommonClassNames.JAVA_UTIL_MAP, "groovy.swing.factory.CellEditorPrepareFactory");
    }

    //private void generateMethods() {
    //  // registerSupportNodes()
    //  beanFactory("groovy.swing.factory.ActionFactory", "action", "javax.swing.Action", true);
    //
    //  add(method("actions", CommonClassNames.JAVA_UTIL_LIST, "groovy.swing.factory.CollectionFactory").addClosureParam());
    //
    //  add(methodWithAttr("map", CommonClassNames.JAVA_UTIL_MAP, "groovy.swing.factory.MapFactory").addClosureParam());
    //
    //  add(acceptAllMethod("imageIcon", "javax.swing.ImageIcon", "groovy.swing.factory.ImageIconFactory")
    //        .setNamedParameters(ImmutableMap.<String, NamedArgumentDescriptor>builder()
    //                              .put("image", new NamedArgumentDescriptor.TypeCondition(type("java.awt.Image")))
    //                              .put("url", new NamedArgumentDescriptor.TypeCondition(type("java.net.URL")))
    //                              .put("file", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //                              .put("resource", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //                              .put("class", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //                              .put("description", NamedArgumentDescriptor.TYPE_STRING)
    //                              .build()
    //        ));
    //
    //  beanFactory("groovy.swing.factory.ButtonGroupFactory", "buttonGroup", "javax.swing.BoxLayout", true);
    //
    //  add(methodWithAttr("noparent", CommonClassNames.JAVA_UTIL_LIST, "groovy.swing.factory.CollectionFactory").addClosureParam());
    //
    //  registerExplicitMethod("keyStrokeAction", "createKeyStrokeAction");
    //  //registerExplicitMethod("shortcut", "shortcut");
    //
    //  // registerBinding()
    //  add(acceptAllMethod("bind", "org.codehaus.groovy.binding.FullBinding", "groovy.swing.factory.BindFactory")
    //        .setNamedParameters(
    //          ImmutableMap.<String, NamedArgumentDescriptor>builder()
    //            .put("source", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .put("target", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .put("update", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .put("targetProperty", NamedArgumentDescriptor.TYPE_STRING)
    //            .put("mutual", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .put("sourceEvent", NamedArgumentDescriptor.TYPE_STRING)
    //            .put("sourceValue", NamedArgumentDescriptor.TYPE_CLOSURE)
    //            .put("sourceProperty", NamedArgumentDescriptor.TYPE_STRING)
    //            .put("value", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .put("bind", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .put("group", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .build()
    //        ));
    //
    //  add(acceptAllMethodLeaf("bindProxy", "org.codehaus.groovy.binding.BindingProxy", "groovy.swing.factory.BindProxyFactory")
    //        .setNamedParameters(
    //          ImmutableMap.<String, NamedArgumentDescriptor>builder()
    //            .put("bind", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .build()
    //        ));
    //
    //  add(acceptAllMethod("bindGroup", "org.codehaus.groovy.binding.AggregateBinding", "groovy.swing.factory.BindGroupFactory")
    //        .setNamedParameters(
    //          ImmutableMap.<String, NamedArgumentDescriptor>builder()
    //            .put("bind", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .build()
    //        ));
    //
    //  // registerPassThruNodes()
    //  add(methodWithAttr("widget", "java.awt.Component", "groovy.swing.factory.WidgetFactory")
    //        .addParameter("component", "java.awt.Component", true)
    //        .setNamedParameters(
    //          ImmutableMap.<String, NamedArgumentDescriptor>of("widget", new NamedArgumentDescriptor.TypeCondition(type("java.awt.Component")))
    //        ));
    //  add(methodWithAttr("container", "java.awt.Component", "groovy.swing.factory.WidgetFactory")
    //        .addParameter("component", "java.awt.Component", true)
    //        .addClosureParam()
    //        .setNamedParameters(
    //          ImmutableMap.<String, NamedArgumentDescriptor>of("container", new NamedArgumentDescriptor.TypeCondition(type("java.awt.Component")))
    //        ));
    //  add(methodWithAttr("bean", CommonClassNames.JAVA_LANG_OBJECT, "groovy.swing.factory.WidgetFactory")
    //        .addParameter("bean", CommonClassNames.JAVA_LANG_OBJECT, true)
    //        .setNamedParameters(
    //          ImmutableMap.<String, NamedArgumentDescriptor>builder()
    //            .put("bean", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .build()
    //        ));
    //
    //  // registerWindows()
    //  add(methodWithAttr("dialog", "javax.swing.JDialog", "groovy.swing.factory.DialogFactory").addParameter("dialog", "javax.swing.JDialog", true).addClosureParam()
    //        .setNamedParameters(
    //          ImmutableMap.<String, NamedArgumentDescriptor>builder()
    //            .put("owner", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .put("defaultButtonProperty", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .put("pack", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .put("show", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //            .build()
    //        ));
    //
    //  beanFactory(null, "fileChooser", "javax.swing.JFileChooser", true);
    //
    //  add(method("frame", "javax.swing.JFrame", "groovy.swing.factory.FrameFactory", "value", "javax.swing.JFrame", true)
    //        .setNamedParameters(
    //          ImmutableMap.<String, NamedArgumentDescriptor>of("pack", NamedArgumentDescriptor.SIMPLE_ON_TOP, "show", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //        )
    //  );
    //
    //  beanFactory(null, "optionPane", "javax.swing.JOptionPane", true);
    //
    //  add(method("window", "javax.swing.JWindow", "groovy.swing.factory.WindowFactory", "window", "javax.swing.JWindow", true)
    //        .setNamedParameters(
    //          ImmutableMap.<String, NamedArgumentDescriptor>of("pack", NamedArgumentDescriptor.SIMPLE_ON_TOP,
    //                                                           "show", NamedArgumentDescriptor.SIMPLE_ON_TOP,
    //                                                           "owner", NamedArgumentDescriptor.SIMPLE_ON_TOP)
    //        )
    //  );
    //
    //  // registerActionButtonWidgets()
    //  add(acceptAllMethod("button", "javax.swing.JButton", "groovy.swing.factory.RichActionWidgetFactory"));
    //  add(acceptAllMethod("checkBox", "javax.swing.JCheckBox", "groovy.swing.factory.RichActionWidgetFactory"));
    //  add(acceptAllMethod("checkBoxMenuItem", "javax.swing.JCheckBoxMenuItem", "groovy.swing.factory.RichActionWidgetFactory"));
    //  add(acceptAllMethod("menuItem", "javax.swing.JMenuItem", "groovy.swing.factory.RichActionWidgetFactory"));
    //  add(acceptAllMethod("radioButton", "javax.swing.JRadioButton", "groovy.swing.factory.RichActionWidgetFactory"));
    //  add(acceptAllMethod("radioButtonMenuItem", "javax.swing.JRadioButtonMenuItem", "groovy.swing.factory.RichActionWidgetFactory"));
    //  add(acceptAllMethod("toggleButton", "javax.swing.JToggleButton", "groovy.swing.factory.RichActionWidgetFactory"));
    //
    //  // registerTextWidgets()
    //  beanFactory("groovy.swing.factory.TextArgWidgetFactory", "editorPane", "javax.swing.JEditorPane", true);
    //  beanFactory("groovy.swing.factory.TextArgWidgetFactory", "label", "javax.swing.JLabel", true);
    //  beanFactory("groovy.swing.factory.TextArgWidgetFactory", "passwordField", "javax.swing.JPasswordField", true);
    //  beanFactory("groovy.swing.factory.TextArgWidgetFactory", "textArea", "javax.swing.JTextArea", true);
    //  beanFactory("groovy.swing.factory.TextArgWidgetFactory", "textField", "javax.swing.JTextField", true);
    //  beanFactory("groovy.swing.factory.TextArgWidgetFactory", "textPane", "javax.swing.JTextPane", true);
    //  add(methodWithAttr("formattedTextField", "javax.swing.JFormattedTextField", "groovy.swing.factory.FormattedTextFactory")
    //      .addClosureParam()
    //      .setNamedParameters(ImmutableMap.<String, NamedArgumentDescriptor>of(
