defmodule Lyn.Router do
  use Lyn.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :no_csrf do
    plug :accepts, ["html"]
    plug :put_secure_browser_headers
  end

  # This plug will look for a Guardian token in the session in the default location
  # Then it will attempt to load the resource found in the JWT.
  # If it doesn't find a JWT in the default location it doesn't do anything
  pipeline :browser_auth do
    plug Guardian.Plug.VerifySession
    plug Guardian.Plug.LoadResource
  end

  # This pipeline is created for use within the admin namespace.
  # It looks for a valid token in the session - but in the 'admin' location of guardian
  # This keeps the session credentials seperate for the main site, and the admin site
  # It's very possible that a user is logged into the main site but not the admin
  # or it could be that you're logged into both.
  # This does not conflict with the browser_auth pipeline.
  # If it doesn't find a JWT in the location it doesn't do anything
  pipeline :admin_browser_auth do
    plug Guardian.Plug.VerifySession, key: :admin
    plug Guardian.Plug.LoadResource, key: :admin
  end

  # We need this pipeline to load the token when we're impersonating.
  # We don't want to load the resource though, just verify the token
  pipeline :impersonation_browser_auth do
    plug Guardian.Plug.VerifySession, key: :admin
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  # This pipeline if intended for API requests and looks for the JWT in the "Authorization" header
  # In this case, it should be prefixed with "Bearer" so that it's looking for
  # Authorization: Bearer <jwt>
  pipeline :api_auth do
    plug Guardian.Plug.VerifyHeader, realm: "Bearer"
    plug Guardian.Plug.LoadResource
  end

  scope "/", Lyn do
    pipe_through [:browser, :browser_auth, :impersonation_browser_auth]

    # Static
    get "/", PageController, :index
    get "/news", PageController, :index
    get "/about", PageController, :index

    # Authentication
    delete "/logout", AuthController, :logout
    resources "/users", UserController
    resources "/authorizations", AuthorizationController
    resources "/tokens", TokenController
  end

  scope "/public", Lyn do
    pipe_through [:no_csrf]

    get "/*filename", PageController, :file
  end

  scope "/auth", Lyn do
    pipe_through [:browser, :browser_auth]


    get "/:identity", AuthController, :login
    get "/:identity/callback", AuthController, :callback
    post "/:identity/callback", AuthController, :callback
  end

  pipeline :webpack do
    plug WebPack.Plug.Static, at: "/public", from: :lyn
  end

  scope "/webpack", Lyn do
    pipe_through :webpack

    get "/stats.json", WebpackController, :stats
    get "/", WebpackController, :index
    get "/events", WebpackController, :events
    get "/client.js", WebpackController, :client
    get "/static/:name", WebpackController, :file
  end


  # This scope is intended for admin users.
  # Normal users can only go to the login page
  scope "/admin", Lyn.Admin, as: :admin do
    pipe_through [:browser, :admin_browser_auth] # Use the default browser stack

    get "/login", SessionController, :new, as: :login
    get "/login/:identity", SessionController, :new
    post "/auth/:identity/callback", SessionController, :callback
    get "/logout", SessionController, :logout
    delete "/logout", SessionController, :logout, as: :logout
    post "/impersonate/:user_id", SessionController, :impersonate, as: :impersonation
    delete "/impersonate", SessionController, :stop_impersonating

    resources "/users", UserController

    get "/", AdminController, :dashboard

    get "/:resource/", AdminController, :index
    get "/:resource/new", AdminController, :new
    get "/:resource/:id/edit", AdminController, :edit
    post "/:resource/", AdminController, :create
    patch "/:resource/:id", AdminController, :update
    put "/:resource/:id", AdminController, :update
    delete "/:resource/:id", AdminController, :delete
    post "/:resource/batch_action", AdminController, :batch_action

    get "/sql", SqlController, :index

    get "/maintenance", MaintenanceController, :index
    get "/maintenance/checkdb", MaintenanceController, :checkdb
    get "/maintenance/reset_cache", MaintenanceController, :reset_cache
    get "/maintenance/dbdump", MaintenanceController, :dbdump
    get "/maintenance/dbload", MaintenanceController, :dbload
    get "/maintenance/system_limits", MaintenanceController, :system_limits
  end

  # Other scopes may use custom stacks.
  # scope "/api", Lyn do
  #   pipe_through :api
  # end
end
