// Path: src/main/java/io/github/proxyprint/kitchen/utils/NotificationManager.java
// public class NotificationManager {
//   
//     private final Logger logger = LoggerFactory.getLogger(WebAppConfig.class);
//     
//     @Autowired
//     private ConsumerDAO consumers;
//     @Autowired
//     private NotificationDAO notifications;
// 
//     private final Multimap<String, SseEmitter> subscriptions;
// 
//     public NotificationManager() {
//         this.subscriptions = HashMultimap.create();
//     }
// 
//     public SseEmitter subscribe(String username) {
//         SseEmitter sseEmitter = new SseEmitter(0l);
//         sseEmitter.onCompletion(new DeleteTask(this, username, sseEmitter));
//         this.subscriptions.put(username, sseEmitter);
//         return sseEmitter;
//     }
// 
//     public void unsubscribe(String username, SseEmitter emitter) {
//         this.subscriptions.remove(username, emitter);
//     }
// 
//     public void sendNotification(String username, Notification notification){
//         Consumer consumer = this.consumers.findByUsername(username);
//         notification = notifications.save(notification);
//         consumer.addNotifications(notification);
//         consumers.save(consumer);
// 
//         if (this.subscriptions.containsKey(username)) {
//             for (SseEmitter sse : this.subscriptions.get(username)) {
//                 try {
//                     sse.send(notification, MediaType.APPLICATION_JSON);
//                 } catch (IOException ex) {
//                     this.logger.warn("Broken SSE Emitter..discarding it...");
//                 }
//             }
//         }
//     }
// 
//     public void removeNotification(long notificationId) {
//         notifications.delete(notificationId);
//     }
// 
//     public void readNotification(long notificationId) {
//         Notification n = notifications.findById(notificationId);
//         n.setReadStatus(true);
//         notifications.save(n);
//     }
// }


import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.github.proxyprint.kitchen.utils.NotificationManager;
import io.github.proxyprint.kitchen.utils.gson.AnnotationExclusionStrategy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.io.IOException;
import org.springframework.scheduling.annotation.EnableAsync;

    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // you USUALLY want this
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PUT");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }

    @Bean
    public Gson gson() {
        return new GsonBuilder().setExclusionStrategies(new AnnotationExclusionStrategy()).create();
    }

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }

    @Bean
    public NotificationManager notificationSubscriptions() {

// Path: src/main/java/io/github/proxyprint/kitchen/utils/NotificationManager.java
// public class NotificationManager {
//   
//     private final Logger logger = LoggerFactory.getLogger(WebAppConfig.class);
//     
//     @Autowired
//     private ConsumerDAO consumers;
//     @Autowired
//     private NotificationDAO notifications;
// 
//     private final Multimap<String, SseEmitter> subscriptions;
// 
//     public NotificationManager() {
//         this.subscriptions = HashMultimap.create();
//     }
// 
//     public SseEmitter subscribe(String username) {
//         SseEmitter sseEmitter = new SseEmitter(0l);
//         sseEmitter.onCompletion(new DeleteTask(this, username, sseEmitter));
//         this.subscriptions.put(username, sseEmitter);
//         return sseEmitter;
//     }
// 
//     public void unsubscribe(String username, SseEmitter emitter) {
//         this.subscriptions.remove(username, emitter);
//     }
// 
//     public void sendNotification(String username, Notification notification){
//         Consumer consumer = this.consumers.findByUsername(username);
//         notification = notifications.save(notification);
//         consumer.addNotifications(notification);
//         consumers.save(consumer);
// 
//         if (this.subscriptions.containsKey(username)) {
//             for (SseEmitter sse : this.subscriptions.get(username)) {
//                 try {
//                     sse.send(notification, MediaType.APPLICATION_JSON);
//                 } catch (IOException ex) {
//                     this.logger.warn("Broken SSE Emitter..discarding it...");
//                 }
//             }
//         }
//     }
// 
//     public void removeNotification(long notificationId) {
//         notifications.delete(notificationId);
//     }
// 
//     public void readNotification(long notificationId) {
//         Notification n = notifications.findById(notificationId);
//         n.setReadStatus(true);
//         notifications.save(n);
//     }
// }


// Path: src/main/java/io/github/proxyprint/kitchen/WebAppConfig.java
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.github.proxyprint.kitchen.utils.NotificationManager;
import io.github.proxyprint.kitchen.utils.gson.AnnotationExclusionStrategy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.io.IOException;
import org.springframework.scheduling.annotation.EnableAsync;

    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // you USUALLY want this
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PUT");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }

    @Bean
    public Gson gson() {
        return new GsonBuilder().setExclusionStrategies(new AnnotationExclusionStrategy()).create();
    }

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }

    @Bean
    public NotificationManager notificationSubscriptions() {

        return new NotificationManager();
