package org.jboss.resteasy.test.cdi.injection.resource;


import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Stateful;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.util.HashMap;
import java.util.logging.Logger;

import static org.jboss.resteasy.test.cdi.injection.resource.ReverseInjectionResource.NON_CONTEXTUAL;

@Stateful
@ApplicationScoped
public class StatefulApplicationScopedEJBwithJaxRsComponents implements StatefulApplicationScopedEJBwithJaxRsComponentsInterface {
   private static HashMap<String, HashMap<String, Object>> store = new HashMap<String, HashMap<String, Object>>();

   private static int constructions;

   private static int destructions;

   @Inject
   int secret;

   public static int getConstructions() {
      return constructions;
   }

   public static int getDestructions() {
      return destructions;
   }

   @PostConstruct
   public void postConstruct() {
      constructions++;
      log.info(this + " secret: " + secret);
   }

   @PreDestroy
   public void preDestroy() {
      destructions++;
   }

   @Inject
   private Logger log;
   @Inject
   private CDIInjectionBookResource resource;
   @Inject
   private CDIInjectionBookReader reader;
   @Inject
   private CDIInjectionBookWriter writer;

   @Override
   public void setUp(String key) {
      log.info("entering StatefulApplicationScopedEJBwithJaxRsComponents.setUp()");
      HashMap<String, Object> substore = new HashMap<String, Object>();
      substore.put("secret", resource.theSecret());
      substore.put(CDIInjectionBookResource.BOOK_READER, reader);
      substore.put(CDIInjectionBookResource.BOOK_WRITER, writer);
      store.put(key, substore);
   }

   /**
    * This is an SFSB. See discussion in ReverseInjectionEJBHolder.test().
    * <p>
    * If NON_CONTEXTUAL.equals(key), then this bean was obtained from JNDI, and
    * it is not a CDI contextual object.  It follows that it is not dependency
    * scoped, which means it will not be recreated, with new injections, upon a
    * second invocation.
    * <p>
    * Otherwise, it will be recreated, and CDI will redo the injections.
    */
   @Override
   public boolean test(String key) {
      log.info("entering StatefulApplicationScopedEJBwithJaxRsComponents.test(" + key + ")");
      HashMap<String, Object> substore = store.get(key);
      int savedSecret = Integer.class.cast(substore.get("secret"));
      log.info("stored resource secret = resource secret: " + (savedSecret == resource.theSecret()));
      log.info("stored reader = reader:                   " + (substore.get(CDIInjectionBookResource.BOOK_READER) == reader));
      log.info("stored writer = writer:                   " + (substore.get(CDIInjectionBookResource.BOOK_WRITER) == writer));

      boolean result = true;
      result &= reader == substore.get(CDIInjectionBookResource.BOOK_READER); // application scoped
      result &= writer == substore.get(CDIInjectionBookResource.BOOK_WRITER); // application scoped
      if (NON_CONTEXTUAL.equals(key)) {
         result &= resource.theSecret() == savedSecret;           // request scope not applicable
      } else {
         result &= resource.theSecret() != savedSecret;           // request scoped
      }
      return result;
   }

   @Override
   public Class<?> theClass() {
      return StatefulApplicationScopedEJBwithJaxRsComponents.class;
   }

   @Override
   public boolean theSame(ReverseInjectionEJBInterface ejb) {
      if (ejb == null) {
         return false;
      }
      Class<?> c = ejb.theClass();
      if (!StatefulApplicationScopedEJBwithJaxRsComponents.class.equals(c)) {
         log.info(ejb + " not instanceof StatefulApplicationScopedEJBwithJaxRsComponents: " + c);
         return false;
      }
      log.info(this.secret + " " + ejb.theSecret());
      return this.secret == ejb.theSecret();
   }

   @Override
   public int theSecret() {
      return secret;
   }
}
