package moe.tristan.easyfxml.model.components.listview;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import moe.tristan.easyfxml.api.FxmlController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javafx.fxml.FXML;
import javafx.scene.control.ListView;

import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.stream.Stream;

@SuppressWarnings("WeakerAccess")
public abstract class CustomListViewBase<T> implements FxmlController {

    private static final Logger LOG = LoggerFactory.getLogger(CustomListViewBase.class);

    private static AtomicBoolean HAS_CHECKED_BEAN_DEFINITIONS = new AtomicBoolean(false);

    @FXML
    protected ListView<T> listView;

    protected final ConfigurableApplicationContext applicationContext;
    protected final Supplier<CustomListViewCellBase<T>> cellSupplier;

    public CustomListViewBase(
        ConfigurableApplicationContext applicationContext,
        Class<? extends CustomListViewCellBase<T>> customCellClass
    ) {
        this.applicationContext = applicationContext;
        this.cellSupplier = () -> applicationContext.getBean(customCellClass);
        ensureCorrectSpringScoping();
    }

    /**
     * You should not need to care about this method.
     * In the unlikely case where you actually want all the cells of your ListView to actually
     * be the same one, it is left protected and not private so you can override it and avoid the
     * warnings being spouted at you.
     *
     * Else, the idea is that a set of cells is created and they share the elements one after
     * another during scrolling and JavaFX might generate more of them later so we should just
     * not make any assumption and expect all of them to be different and not singletons.
     */
    protected void ensureCorrectSpringScoping() {
        if (HAS_CHECKED_BEAN_DEFINITIONS.get()) return;

        final ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        Stream.of(CustomListViewCellController.class, CustomListViewCellBase.class)
              .map(beanFactory::getBeanNamesForType)
              .flatMap(Arrays::stream)
              .forEach(pBean -> {
                  final String effectiveScope = beanFactory.getBeanDefinition(pBean).getScope();
                  if (ConfigurableBeanFactory.SCOPE_PROTOTYPE.equals(effectiveScope)) {
                      LOG.warn(
                              "Custom ListView cells wrappers and controllers should be prototype-scoped bean. " +
                              "See @Scope annotation.\n" +
                              "Faulty bean was named : \"{}\"",
                              pBean
                      );
                  }
              });
        HAS_CHECKED_BEAN_DEFINITIONS.set(true);
    }

    @Override
    public void initialize() {
        setCustomCellFactory();
    }

    private void setCustomCellFactory() {
        listView.setCellFactory(list -> cellSupplier.get());
    }

}

@@ -801,16 +801,22 @@
  static 
+final 
 AtomicBo
@@ -2044,24 +2044,82 @@
 Scoping() %7B%0A
+        synchronized (HAS_CHECKED_BEAN_DEFINITIONS) %7B%0A    
         if (
@@ -2163,16 +2163,20 @@
 eturn;%0A%0A
+    
         
@@ -2260,24 +2260,28 @@
 nFactory();%0A
+    
         Stre
@@ -2366,16 +2366,20 @@
         
+    
 .map(bea
@@ -2423,16 +2423,20 @@
         
+    
 .flatMap
@@ -2466,16 +2466,20 @@
         
+ 
+   
 .forEach
@@ -2490,16 +2490,20 @@
 an -%3E %7B%0A
+    
         
@@ -2605,24 +2605,28 @@
             
+ 
+   
 if (Configur
@@ -2705,16 +2705,20 @@
         
+    
 LOG.warn
@@ -2749,16 +2749,20 @@
         
+ 
+   
 %22Custom 
@@ -2868,16 +2868,20 @@
         
+    
 %22See @Sc
@@ -2931,16 +2931,20 @@
         
+ 
+   
 %22Faulty 
@@ -2999,16 +2999,20 @@
         
+    
 pBean%0A  
@@ -3031,16 +3031,20 @@
         
+  
+  
 );%0A     
@@ -3056,18 +3056,24 @@
         
-%7D%0A
+    %7D%0A  
         
@@ -3082,12 +3082,18 @@
     
+  
 %7D);%0A
+    
     
@@ -3136,16 +3136,26 @@
 (true);%0A
+        %7D%0A
     %7D%0A%0A 

Fix multi-thread modeling of CustomListViewBase bean runtime check