content: import com.github.mustachejava.DefaultMustacheFactory;
  import com.github.mustachejava.Mustache;
  import io.activej.bytebuf.ByteBuf;
  import io.activej.bytebuf.util.ByteBufWriter;
  import io.activej.http.AsyncServlet;
  import io.activej.http.HttpResponse;
  import io.activej.http.RoutingServlet;
  import io.activej.inject.annotation.Provides;
  import io.activej.launcher.Launcher;
  import io.activej.launchers.http.HttpServerLauncher;
  import io.activej.reactor.Reactor;
  
  import java.util.List;
  import java.util.Map;
  
  import static io.activej.common.Utils.nonNullElse;
  import static io.activej.http.HttpHeaders.REFERER;
  import static io.activej.http.HttpMethod.GET;
  import static io.activej.http.HttpMethod.POST;
  
  //[START REGION_1]
  public final class ApplicationLauncher extends HttpServerLauncher {
  
  	private static ByteBuf applyTemplate(Mustache mustache, Map<String, Object> scopes) {
  		ByteBufWriter writer = new ByteBufWriter();
  		mustache.execute(writer, scopes);
  		return writer.getBuf();
  	}
  
  	@Provides
  	PollDao pollRepo() {
  		return new PollDaoImpl();
  	}
  
  	//[END REGION_1]
  	//[START REGION_2]
  	@Provides
  	AsyncServlet servlet(Reactor reactor, PollDao pollDao) {
  		Mustache singlePollView = new DefaultMustacheFactory().compile("templates/singlePollView.html");
  		Mustache singlePollCreate = new DefaultMustacheFactory().compile("templates/singlePollCreate.html");
  		Mustache listPolls = new DefaultMustacheFactory().compile("templates/listPolls.html");
  
  		return RoutingServlet.builder(reactor)
  			.with(GET, "/", request -> HttpResponse.ok200()
  				.withBody(applyTemplate(listPolls, Map.of("polls", pollDao.findAll().entrySet())))
  				.toPromise())
  			//[END REGION_2]
  			//[START REGION_3]
  			.with(GET, "/poll/:id", request -> {
  				int id = Integer.parseInt(request.getPathParameter("id"));
  				return HttpResponse.ok200()
  					.withBody(applyTemplate(singlePollView, Map.of("id", id, "poll", pollDao.find(id))))
  					.toPromise();
  			})
  			//[END REGION_3]
  			//[START REGION_4]
  			.with(GET, "/create", request ->
  				HttpResponse.ok200()
  					.withBody(applyTemplate(singlePollCreate, Map.of()))
  					.toPromise())
  			.with(POST, "/vote", request -> request.loadBody()
  				.then(() -> {
  					Map<String, String> params = request.getPostParameters();
  					String option = params.get("option");
  					String stringId = params.get("id");
  					if (option == null || stringId == null) {
  						return HttpResponse.ofCode(401).toPromise();
  					}
  
  					int id = Integer.parseInt(stringId);
  					PollDao.Poll question = pollDao.find(id);
  
  					question.vote(option);
  
  					return HttpResponse.redirect302(nonNullElse(request.getHeader(REFERER), "/")).toPromise();
  				}))
  			.with(POST, "/add", request -> request.loadBody()
  				.then($ -> {
  					Map<String, String> params = request.getPostParameters();
  					String title = params.get("title");
  					String message = params.get("message");
  
  					String option1 = params.get("option1");
  					String option2 = params.get("option2");
  
  					int id = pollDao.add(new PollDao.Poll(title, message, List.of(option1, option2)));
  					return HttpResponse.redirect302("poll/" + id).toPromise();
  				}))
  			.with(POST, "/delete", request -> request.loadBody()
  				.then(() -> {
  					Map<String, String> params = request.getPostParameters();
  					String id = params.get("id");
  					if (id == null) {
  						return HttpResponse.ofCode(401).toPromise();
  					}
  					pollDao.remove(Integer.parseInt(id));
  
  					return HttpResponse.redirect302("/").toPromise();
  				}))
  			.build();
  		//[END REGION_4]
  	}
  
  	//[START REGION_5]
  	public static void main(String[] args) throws Exception {
  		Launcher launcher = new ApplicationLauncher();
  		launcher.launch(args);
  	}
  	//[END REGION_5]
  }
  