package com.conveyal.analyst.server;

import com.conveyal.analyst.server.controllers.*;

import static spark.Spark.*;

/**
 * Routes for Analyst Server.
 */
public class Routes {
    private static final JsonTransformer json = new JsonTransformer();

    public static void routes () {
        // serve assets
        staticFileLocation("/public");

        // send people to the login page if necessary
        before("/", Authentication::uiAuthenticated);

        // messages are dynamically generated
        get("/messages", MessagesController::messages);

        // login/logout/admin
        post("/doLogin", Application::doLogin);
        post("/createUser", Application::createUser);

        before("/setPassword", Authentication::authenticated);
        post("/setPassword", Application::setPassword);

        // TODO this shouldn't be a GET as it's not idempotent
        get("/logout", Application::logout);

        before("/createDemoProject", Authentication::authenticated);
        get("/createDemoProject", Application::createDemoProject);

        // user controllers
        // TODO ensure / matches /api/user
        before("/api/user*", Authentication::authenticated);
        get("/api/user", UserController::getUser, json);
        get("/api/user/:id", UserController::getUser, json);
        delete("/api/user", UserController::deleteUser, json);
        after("/api/user", json::type);

        // TODO edit user: slightly tricky due to the hashed password

        // project routes
        before("/api/project*", Authentication::authenticated);
        // return value is plain text
        get("/api/project/:id/exemplarDay", ProjectController::getExemplarDay);
        get("/api/project", ProjectController::getProject, json);
        get("/api/project/:id", ProjectController::getProject, json);
        post("/api/project", ProjectController::createProject, json);
        put("/api/project/:id", ProjectController::updateProject, json);
        delete("/api/project/:id", ProjectController::deleteProject, json);
        after("/api/project*", json::type);

        // shapefile routes
        before("/api/shapefile*", Authentication::authenticated);
        get("/api/shapefile", ShapefileController::getShapefile, json);
        get("/api/shapefile/:id", ShapefileController::getShapefile, json);
        post("/api/shapefile", ShapefileController::createShapefile, json);
        put("/api/shapefile/:id", ShapefileController::updateShapefile, json);
        delete("/api/shapefile/:id", ShapefileController::deleteShapefile, json);
        after("/api/shapefile*", json::type);

        // bundle routes
        before("/api/bundle*", Authentication::authenticated);
        get("/api/bundle", BundleController::getBundle, json);
        get("/api/bundle/:id", BundleController::getBundle, json);
        post("/api/bundle", BundleController::createBundle, json);
        put("/api/bundle/:id", BundleController::updateBundle, json);
        delete("/api/bundle/:id", BundleController::deleteBundle, json);
        after("/api/bundle*", json::type);

        // scenario routes
        before("/api/scenario*", Authentication::authenticated);
        get("/api/scenario", ScenarioController::get, json);
        get("/api/scenario/:id", ScenarioController::getById, json);
        post("/api/scenario", ScenarioController::create, json);
        put("/api/scenario/:id", ScenarioController::update, json);
        delete("/api/scenario/:id", ScenarioController::delete, json);
        after("/api/scenario*", json::type);

        // query routes
        // note: auth is handled by each individual controller as some allow unauthenticated access
        get("/api/query", QueryController::getQuery, json);
        get("/api/query/:id", QueryController::getQuery, json);
        post("/api/query", QueryController::createQuery, json);
        put("/api/query/:id", QueryController::updateQuery, json);
        delete("/api/query/:id", QueryController::deleteQuery, json);
        get("/api/query/:id/bins", QueryController::queryBins, json);
        get("/api/query/:id/:compareTo/bins", QueryController::queryBins, json);
        after("/api/query*", json::type);

        // single point analysis results
        // note: auth is handled in the controller
        // JSON rendered by controller, no need for a result filter
        post("/api/single", SinglePoint::result);
        options("/api/single", SinglePoint::options);
        after("/api/single*", json::type);

        get("/csv/single", SinglePoint::csv);

        // GIS routes
        before("/gis*", Authentication::authenticated);
        get("/gis/query", Gis::query);
        get("/gis/single", Gis::single);
        get("/gis/singleComparison", Gis::singleComparison);

        // all tiles are accessible by the world if unauthenticated API access is enabled.
        before("/tile*", Authentication::authenticatedOrCors);
        get("/tile/spatial", Tiles::spatial);
        get("/tile/shapefile", Tiles::shape);
        get("/tile/query/:queryId/:compareTo/:z/:x/:yformat", Tiles::query);
        get("/tile/query/:queryId/:z/:x/:yformat", Tiles::query);
        get("/tile/transit", Tiles::transit);
        get("/tile/transitComparison", Tiles::transitComparison);
        get("/tile/single/:key/:z/:x/:yformat", SinglePointTiles::single);
        get("/tile/single/:key1/:key2/:z/:x/:yformat", SinglePointTiles::compare);
    }
}

@@ -1069,96 +1069,463 @@
  // 
-user controllers%0A        // TODO ensure / matches /api/user%0A        before(%22/api/user*%22,
+authentication for API excludes two resources%0A        before(%22/api/*%22, (req, res) -%3E %7B%0A            // single and query allow CORS access and auth is handled in controllers%0A            String%5B%5D whitelist = new String%5B%5D %7B%0A                    %22/api/single%22,%0A                    %22/api/query%22%0A            %7D;%0A%0A            for (String root : whitelist) %7B%0A                if (req.pathInfo().startsWith(root))%0A                    return;%0A            %7D%0A%0A           
  Aut
@@ -1527,34 +1527,33 @@
   Authentication
-::
+.
 authenticated);%0A
@@ -1541,34 +1541,127 @@
 on.authenticated
-);
+(req, res);%0A        %7D);%0A%0A        // user controllers%0A        // TODO ensure / matches /api/user
 %0A        get(%22/a
@@ -1968,72 +1968,8 @@
 tes%0A
-        before(%22/api/project*%22, Authentication::authenticated);%0A
     
@@ -2514,74 +2514,8 @@
 tes%0A
-        before(%22/api/shapefile*%22, Authentication::authenticated);%0A
     
@@ -2971,71 +2971,8 @@
 tes%0A
-        before(%22/api/bundle*%22, Authentication::authenticated);%0A
     
@@ -3382,73 +3382,8 @@
 tes%0A
-        before(%22/api/scenario*%22, Authentication::authenticated);%0A
     
@@ -4700,33 +4700,32 @@
 %22, json::type);%0A
-%0A
         get(%22/cs
@@ -4797,16 +4797,17 @@
 re(%22/gis
+/
 *%22, Auth
@@ -5088,16 +5088,17 @@
 e(%22/tile
+/
 *%22, Auth

fix auth.