package com.lowtuna.jsonblob;

import com.codahale.metrics.Gauge;
import com.codahale.metrics.MetricRegistry;
import com.github.jknack.handlebars.Handlebars;
import com.lowtuna.dropwizard.extras.heroku.RequestIdFilter;
import com.lowtuna.dropwizard.extras.view.handlebars.ConfiguredHandlebarsViewBundle;
import com.lowtuna.jsonblob.config.JsonBlobConfiguration;
import com.lowtuna.jsonblob.core.BlobManager;
import com.lowtuna.jsonblob.healthcheck.MongoHealthCheck;
import com.lowtuna.jsonblob.resource.ApiResource;
import com.lowtuna.jsonblob.resource.JsonBlobEditorResource;
import com.lowtuna.jsonblob.util.jersey.GitTipHeaderFilter;
import com.lowtuna.jsonblob.util.mongo.JacksonMongoDbModule;
import com.mongodb.DB;
import io.dropwizard.Application;
import io.dropwizard.assets.AssetsBundle;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.joda.time.Duration;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;

import javax.servlet.FilterRegistration;

@Slf4j
public class JsonBlobApplication extends Application<JsonBlobConfiguration> {

    private final long startTIme = System.currentTimeMillis();
    private final PeriodFormatter uptimePeriodFormatter = new PeriodFormatterBuilder()
            .appendDays()
            .appendSuffix("d")
            .appendHours()
            .appendSuffix("h")
            .appendMinutes()
            .appendSuffix("m")
            .appendSeconds()
            .appendSuffix("s")
            .toFormatter();

    public static void main(String[] args) throws Exception {
        if (args.length >= 2 && args[1].startsWith("~")) {
            args[1] = System.getProperty("user.home") + args[1].substring(1);
        }
        new JsonBlobApplication().run(args);
    }

    @Override
    public String getName() {
        return "jsonblob";
    }

    @Override
    public void initialize(final Bootstrap<JsonBlobConfiguration> bootstrap) {
        bootstrap.addBundle(new AssetsBundle());

        bootstrap.addBundle(new ConfiguredHandlebarsViewBundle<JsonBlobConfiguration>() {
            @Override
            public Handlebars getInstance(JsonBlobConfiguration configuration) {
                log.info("Using Handlebars configuration of {}", configuration.getHandlebarsConfig().getClass().getCanonicalName());
                return configuration.getHandlebarsConfig().getInstance(bootstrap.getMetricRegistry());
            }
        });
    }

    @Override
    public void run(JsonBlobConfiguration configuration, Environment environment) throws ClassNotFoundException {
        environment.metrics().register(MetricRegistry.name(getClass(), "uptime"), new Gauge<String>() {
            @Override
            public String getValue() {
                return uptimePeriodFormatter.print(new Duration(System.currentTimeMillis() - startTIme).toPeriod());
            }
        });

        environment.getObjectMapper().registerModule(new JacksonMongoDbModule());

        DB mongoDBInstance = configuration.getMongoDbConfig().instance();

        BlobManager blobManager = new BlobManager(
                mongoDBInstance,
                configuration.getBlobManagerConfig().getBlobCollectionName(),
                configuration.getBlobManagerConfig().getScheduledExecutorService().instance(environment),
                configuration.getBlobManagerConfig().getBlobCleanupFrequency(),
                configuration.getBlobManagerConfig().getBlobAccessTtl(),
                environment.metrics(),
                configuration.getBlobManagerConfig().isDeleteEnabled()
        );
        environment.lifecycle().manage(blobManager);

        environment.healthChecks().register("MongoDB", new MongoHealthCheck(mongoDBInstance));

        environment.jersey().register(new ApiResource(blobManager, configuration.getGoogleAnalyticsConfig()));
        environment.jersey().register(new JsonBlobEditorResource(blobManager, configuration.getGoogleAnalyticsConfig()));
        environment.jersey().getResourceConfig().getContainerResponseFilters().add(new GitTipHeaderFilter());
        environment.jersey().getResourceConfig().getContainerRequestFilters().add(new RequestIdFilter("X-Request-ID"));

        FilterRegistration.Dynamic corsFilterRegistration = environment.servlets().addFilter("cross-origin", CrossOriginFilter.class);
        corsFilterRegistration.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,POST,PUT,DELETE,HEAD");
        corsFilterRegistration.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,X-jsonblob,Content-Type,Accept,Origin");
    }

}

@@ -714,16 +714,186 @@
 odb.DB;%0A
+import com.sun.jersey.spi.container.ContainerRequest;%0Aimport com.sun.jersey.spi.container.ContainerResponse;%0Aimport com.sun.jersey.spi.container.ContainerResponseFilter;%0A
 import i
@@ -914,24 +914,24 @@
 pplication;%0A
-
 import io.dr
@@ -1087,48 +1087,40 @@
 org.
-eclipse.jetty.servlets.CrossOriginFilter
+apache.commons.lang3.StringUtils
 ;%0Aim
@@ -1263,34 +1263,33 @@
 vax.
-servlet.FilterRegistration
+ws.rs.core.MultivaluedMap
 ;%0A%0A@
@@ -4494,59 +4494,31 @@
     
-FilterRegistration.Dynamic corsFilterRegistration =
+// Support CORS%0A       
  env
@@ -4530,334 +4530,756 @@
 ent.
-servlets().addFilter(%22cross-origin%22, CrossOriginFilter.class);%0A        corsFilterRegistrati
+jersey().getResourceConfig().getContainerResponseFilters().add(new ContainerResponseFilter() %7B%0A            @Override%0A            public ContainerResponse filter(ContainerRequest request, ContainerResp
 on
-.
 se
-tInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM
+ response) %7B%0A                MultivaluedMap headers = response.getHttpHeaders();%0A                headers.add(%22Access-Control-Allow-Origin%22, %22*%22);%0A                headers.add(%22Access-Control-Allow-Methods%22
 , %22GET,
+ 
 POST,
+ 
 PUT,
+ 
 DELETE,
+ 
 HEAD
-%22);%0A        corsFilterRegistration.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, %22X-Requested-With,X-jsonblob,Content-Type,Accept,Origin%22
+, OPTIONS%22);%0A%0A                String reqHead = request.getHeaderValue(%22Access-Control-Request-Headers%22);%0A                if (StringUtils.isNotEmpty(reqHead)) %7B%0A                    headers.add(%22Access-Control-Allow-Headers%22, reqHead);%0A                %7D%0A%0A                return response;%0A            %7D%0A        %7D
 );%0A 

add CORS support