package com.packtpub.hibernatesearch.util;

import javax.servlet.ServletContextEvent;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.packtpub.hibernatesearch.domain.App;

/**
 * Klasa pomocniczna używana do zapełnienia wbudowanej bazy H2 testowymi danymi podczas startu aplikacji. 
 * Dzięki ustawieniom w pliku "web.xml", metoda "contextInitialized" będzie automatycznie wywołana podczas 
 * startu kontenera servletów.
 */
public class StartupDataLoader implements javax.servlet.ServletContextListener {
	
	Logger logger = LoggerFactory.getLogger(StartupDataLoader.class);

	/**
	 * Nie powinna być używana bezpośrednio. Użyj openSession().
	 */
	private static SessionFactory sessionFactory;
	
	/**
	 * Konstruowanie nowej SessionFactory Hibernate dla każdego żądania HTTP powodowałoby problemy wydajnościowe. Ponieważ
	 * servlety Javy muszą być współbieżne, nie możemy zadeklarować by SessionFactory była publiczną statyczną zmienną.
	 * Ta metoda udostępnia współbieżny dostęp do SessionFactory, dzięki czemu metoda zapełniająca bazę danych przykładowymi danymi 
	 * i servlet wyszukujący mogą otwierać połączenia do bazy danych bardziej wydajnie. 
	 * 
	 * @return Session
	 */
	public static synchronized Session openSession() {
		if(sessionFactory == null) {
			Configuration configuration = new Configuration();
			configuration.configure();
			ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
			sessionFactory = configuration.buildSessionFactory(serviceRegistry);			
		}
		return sessionFactory.openSession();
	}

	/**
	 * Ta metoda jest uruchamiana automatycznie gdy uruchomiony zostaje mechanizm servletów.
	 */
	public void contextInitialized(ServletContextEvent event) {

		//
		// Utwórz sesję Hibernate i rozpocznij nową transakcję bazodanową.
		//
		Session session = openSession();
		session.beginTransaction();
		
		//
		// Utwórz i zapisz 12 testowyc aplikacji
		//
		App app1 = new App("Chmura!", "cloud.jpg", "Aplikacja Chmura! jest miejscem, w którym dzieją się cuda. Firmy działają w chmurach. Programiści nie potrzebują administratorów, jedzenia i picia w zasadzie też nie. Możesz oglądać telewizję na tablecie, siedzać na kanapie; nie musisz w ogóle patrzeć na telewizor! Ściągnij aplikację Chmura! z chmury i doświadcz tej cudownej potęgi!");
		session.save(app1);
		logger.info("Zapisuję " + app1.getName());

		App app2 = new App("Zamykacz transakcji", "pointing.jpg", "Wysokoenergetyczna aplikacja wspomagająca energicznych sprzedawców. Twórz pełne energii kalendarze i arkusze. Gdy jesteś w mieście i energicznie nawiązujesz kontakty, chcesz prezentować swe naenergetyzowane foldery, pokazujące, że też masz w sobie mnóstwo energii.");
		session.save(app2);
		logger.info("Zapisuję " + app2.getName());

		App app3 = new App("Międzynarodowy turniej piłkarski", "ball.jpg", "Ta mała aplikacja oferuje Ci radość gry w piłkę nożną, poza tym, że grasz na ekranie dotykowym, zamiast biegać i kopać albo w ogóle się ruszać. Poza tym zapewnia podobne wrażenia.");
		session.save(app3);
		logger.info("Zapisuję " + app3.getName());
		
		App app4 = new App("Kolejna gra o kryształach", "brilliant.jpg", "Olśniewająca aplikacja, w której łączysz kryształy tego samego koloru, by zniknęły. Coś jak Tetris. W sumie przypomina tuzin innych gier, w których łączysz kryształy tego samego koloru.");
		session.save(app4);
		logger.info("Zapisuję " + app4.getName());
		
		App app5 = new App("Temperówka", "pencil.jpg", "Ostrz ołówki, wkładając je do gniazda Bluetooth i wciskając przycisk. Ta aplikacja wyciska ze sprzętu wszystko!");
		session.save(app5);
		logger.info("Zapisuję " + app5.getName());
		
		App app6 = new App("Namierzacz zszywaczy", "stapler.jpg", "Czy ktoś ciągle pożycza sobie Twój zszywacz? To typowy problem w biurach. Nasza aplikacja biznesowa sprawi, że już nigdy nie będziesz musiał się zastanawiać, gdzie podziewa się Twój zszywacz.");
		session.save(app6);
		logger.info("Zapisuję " + app6.getName());
		
		App app7 = new App("Sfrustrowane Flamingi", "flamingo.jpg", "Mała aplikacja pozwalająca na ciskanie wielkimi ptakami na lewo i prawo bez powodu. Chyba nie zastanawiasz się czemu są sfrustrowane?");
		session.save(app7);
		logger.info("Zapisuję " + app7.getName());
		
		App app8 = new App("Wideokonferencje Grype", "laptop.jpg", "Dzwoń za darmo lokalnie i za granicę, również z transmisją obrazu, używając domowego połączenia internetowego i naszego produktu. W sumie nasz aplikacja zadziała jeszcze lepiej jeśli skorzystasz z połączenia internetowego Twojego pracodawcy!");
		session.save(app8);
		logger.info("Zapisuję " + app8.getName());
		
		App app9 = new App("Czytnik E-Booków", "book.jpg", "Nasza aplikacja sprawi, że będziesz mógł czytać książki na komputerze albo na dowolnym urządzeniu mobilnym.  Polecamy \"Hibernate Search by Example\".");
		session.save(app9);
		logger.info("Zapisuję " + app9.getName());
		
		App app10 = new App("Przeglądarka pod kopułą", "orangeswirls.jpg", "Ta cudowna aplikacja pozwala nam śledzić Twoją aktywność w Internecie. Możemy odgadnąć, gdzie mieszkasz, co jadłeś dzisiaj na śniadanie albo jakie są Twoje największe sekrety. Aha, w aplikację jest jeszcze wbudowana przeglądarka stron WWW.");
		session.save(app10);
		logger.info("Zapisuję " + app10.getName());
		
		App app11 = new App("Internetowe radio Atena", "jamming.jpg", "Słuchaj swoich ulubionych piosenek w radiu internetowym! Kiedy polubisz jakiś utwór, nasza aplikacja zagra Ci więcej podobnych kompozycji. A przynajmniej zagra więcej piosenek ... Żeby być szczerym, czasem wcale nie są takie podobne  :(");
		session.save(app11);
		logger.info("Zapisuję " + app11.getName());
		
		App app12 = new App("Mapa podróży", "compass.jpg", "Potrzebujesz wskazówek, by dotrzeć do celu?  Nasza aplikacja GPS na pewno wygeneruje wystarczająco dużo propozycji, byś dotarł do celu!  Prędzej czy później.");
		session.save(app12);
		logger.info("Zapisuję " + app12.getName());
		
		session.getTransaction().commit();
		
		//
		// Zamknij i wyczyść sesję Hibernate
		//
		session.close();
	} 

	/**
	 * Ta metoda jest wywoływana gdy mechanizm servletów jest wyłączany. Zamyka Hibernate SessionFactory jeżeli jeszcze jest otwarta.
	 */
	public void contextDestroyed(ServletContextEvent event) {
		if(!sessionFactory.isClosed()) {
			sessionFactory.close();
		}
	}

}
