# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Static resources
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /assets/*file                                controllers.Assets.versioned(path="/public", file: Asset)
->      /webjars                                     webjars.Routes
GET     /favicon.ico                                 controllers.Assets.at(path="/public", file="/images/favicon.png")

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Landing area
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /signup                                      controllers.landing.SignupController.showSignupForm
POST    /signup                                      controllers.landing.SignupController.processSignup
GET     /login                                       controllers.landing.LoginLogoutController.showLoginForm(destination: Option[String] ?= None)
POST    /login                                       controllers.landing.LoginLogoutController.processLogin
GET     /login/confirm-announcment                   controllers.landing.LoginLogoutController.confirmServiceAnnouncement(id: java.util.UUID, response: String, destination: Option[String] ?= None)
GET     /logout                                      controllers.landing.LoginLogoutController.logout
GET     /reset_password                              controllers.landing.ResetPasswordController.showResetForm
POST    /reset_password                              controllers.landing.ResetPasswordController.resetPassword
GET     /status                                      controllers.landing.StatusController.index

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Help area
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /help/about                                  controllers.help.HelpController.about
GET     /help/faq                                    controllers.help.HelpController.faq
GET     /help/privacy                                controllers.help.HelpController.privacy
GET     /help/relations                              controllers.help.HelpController.relations
GET     /help/cloning                                controllers.help.HelpController.cloning
GET     /help/sharing-links                          controllers.help.HelpController.sharingLinks
GET     /help/terms                                  controllers.help.HelpController.terms
GET     /help/tutorial                               controllers.help.HelpController.tutorial
GET     /help/workspace                              controllers.help.HelpController.workspace
GET     /help/:lang/tutorial                         controllers.help.HelpController.localizedTutorial(lang: String)
GET     /help/api-doc                                controllers.help.HelpController.swaggerUi
GET     /help                                        controllers.help.HelpController.index

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Administration area
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /admin/authorities                           controllers.admin.authorities.AuthoritiesAdminController.index
POST    /admin/authorities                           controllers.admin.authorities.AuthoritiesAdminController.upsertAuthority
DELETE  /admin/authorities/:name                     controllers.admin.authorities.AuthoritiesAdminController.deleteGazetteer(name: String)

GET     /admin/users.json                            controllers.admin.users.UserAdminController.listUsers(offset: Int ?= 0, size: Int ?= 100, sortBy: Option[String] ?= None, sortOrder: Option[String] ?= None)
GET     /admin/idle-users.json                       controllers.admin.users.UserAdminController.listIdleUsers(since: String, offset: Int ?= 0, size: Int ?= 100)
PUT     /admin/user/:username                        controllers.admin.users.UserAdminController.updateSettings(username: String)
DELETE  /admin/user/:username                        controllers.admin.users.UserAdminController.deleteAccount(username: String)
GET     /admin/users                                 controllers.admin.users.UserAdminController.index

GET     /admin/visits/export                         controllers.admin.backup.BackupAdminController.exportVisits
GET     /admin/visits/purge                          controllers.admin.backup.BackupAdminController.deleteVisitsOlderThan(date: Option[String])

GET     /admin/maintenance                           controllers.admin.maintenance.MaintenanceController.index
GET     /admin/maintenance/uploads.json              controllers.admin.maintenance.MaintenanceController.listPendingUploads
DELETE  /admin/maintenance/uploads                   controllers.admin.maintenance.MaintenanceController.deleteAllPending
GET     /admin/maintenance/filestore/size.json       controllers.admin.maintenance.MaintenanceController.getFilestoreSize
GET     /admin/maintenance/elasticsearch/props.json  controllers.admin.maintenance.MaintenanceController.getIndexProps
GET     /admin/maintenance/logs/path.json            controllers.admin.maintenance.MaintenanceController.getLogLocation
POST    /admin/maintenance/restore                   controllers.admin.backup.BackupAdminController.restore
GET     /admin/maintenance/broadcast                 controllers.admin.maintenance.MaintenanceController.insertBroadcast
GET     /admin/maintenance/broadcast/_deleteAll      controllers.admin.maintenance.MaintenanceController.deleteAllServiceAnnouncements


GET     /admin/stats.json                            controllers.admin.AdminController.getStats
GET     /admin/signups.json                          controllers.admin.AdminController.getSignupHistory
GET     /admin                                       controllers.admin.AdminController.index

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Document views
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /document/:id/part/:seqNo/edit               controllers.document.annotation.AnnotationController.showAnnotationView(id: String, seqNo: Int)

GET     /document/:id/map                            controllers.document.map.MapController.showMap(id: String)

GET     /document/:id/stats                          controllers.document.stats.StatsController.showDocumentStats(id: String, tab: Option[String])
GET     /document/:id/stats/tags.json                controllers.document.stats.StatsController.getTagsAsJSON(id: String)
GET     /document/:id/stats/tags.csv                 controllers.document.stats.StatsController.getTagsAsCSV(id: String)

GET     /document/:id/downloads                      controllers.document.downloads.DownloadsController.showDownloadOptions(id: String)
GET     /document/:id/downloads/annotations/csv      controllers.document.downloads.DownloadsController.downloadCSV(id: String, export_tables: Boolean ?= false)
GET     /document/:id/downloads/annotations/ttl      controllers.document.downloads.DownloadsController.downloadTTL(id: String)
GET     /document/:id/downloads/annotations/rdf      controllers.document.downloads.DownloadsController.downloadRDFXML(id: String)
GET     /document/:id/downloads/annotations/jsonld   controllers.document.downloads.DownloadsController.downloadJSONLD(id: String, flavour: Option[String])
GET     /document/:id/downloads/places/geojson       controllers.document.downloads.DownloadsController.downloadGeoJSON(id: String, as_gazetteer: Boolean ?= false)
POST    /document/:id/downloads/places/geojson       controllers.document.downloads.DownloadsController.downloadGeoJSON(id: String, as_gazetteer: Boolean ?= false)
GET     /document/:id/downloads/places/kml           controllers.document.downloads.DownloadsController.downloadKML(id: String, geobrowser: Boolean ?= false)
GET     /document/:id/downloads/relations/csv        controllers.document.downloads.DownloadsController.downloadRelationTriples(id: String)
GET     /document/:id/downloads/relations/node-csv   controllers.document.downloads.DownloadsController.downloadGephiNodes(id: String)
GET     /document/:id/downloads/relations/edge-csv   controllers.document.downloads.DownloadsController.downloadGephiEdges(id: String)
GET     /document/:id/downloads/merged/tei           controllers.document.downloads.DownloadsController.downloadTEI(id: String)
GET     /document/:id/downloads/iob                  controllers.document.downloads.DownloadsController.downloadIOB(id: String)
GET     /document/:id/downloads/spacy.json           controllers.document.downloads.DownloadsController.downloadSpacy(id: String)

GET     /document/:id/discussion                     controllers.document.discussion.DiscussionController.showDiscussionBoard(id: String)

PUT     /document/:id/settings/sortorder             controllers.document.settings.SettingsController.setSortOrder(id: String)
GET     /document/:id/settings                       controllers.document.settings.SettingsController.showDocumentSettings(id: String, tab: Option[String])
POST    /document/:id/settings/metadata              controllers.document.settings.SettingsController.updateDocumentMetadata(id: String)
POST    /document/:id/settings/metadata/part/:ptId   controllers.document.settings.SettingsController.updateFilepartMetadata(id: String, ptId: java.util.UUID)
POST    /document/:id/settings/prefs/gazetteers      controllers.document.settings.SettingsController.setGazetteerPreferences(id: String)
PUT     /document/:id/settings/visibility            controllers.document.settings.SettingsController.setPublicVisibility(id: String, visibility: String)
PUT     /document/:id/settings/accesslevel           controllers.document.settings.SettingsController.setPublicAccessLevel(id: String, accessLevel: String)
PUT     /document/:id/settings/collaborator          controllers.document.settings.SettingsController.addCollaborator(id: String)
DELETE  /document/:id/settings/collaborator/:user    controllers.document.settings.SettingsController.removeCollaborator(id: String, user: String)
GET     /document/:id/settings/collaborator/search   controllers.document.settings.SettingsController.searchUsers(id: String, q: String)
GET     /document/:id/settings/history.json          controllers.document.settings.SettingsController.getContributionHistory(id: String, offset: Int ?= 0, size: Int ?= 100)
POST    /document/:id/settings/rollback              controllers.document.settings.SettingsController.rollbackByTime(id: String, contributionId: String)
GET     /document/:id/settings/zip-export            controllers.document.settings.SettingsController.exportAsZip(id: String)
DELETE  /document/:id/settings/delete-annotations    controllers.document.settings.SettingsController.deleteAnnotations(id: String)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Document content
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /document/:id/part/:partNo/manifest          controllers.document.DocumentController.getImageManifest(id: String, partNo: Int)
GET     /document/:id/part/:partNo/tiles/*path       controllers.document.DocumentController.getImageTile(id: String, partNo: Int, path: String)
GET     /document/:id/part/:partNo/thumb.jpg         controllers.document.DocumentController.getThumbnail(id: String, partNo: Int)
GET     /document/:id/part/:partNo/raw               controllers.document.DocumentController.getRaw(id: String, partNo: Int, lines: Option[Int] ?= None)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Document base path
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /document/:id                                controllers.document.DocumentController.initialDocumentView(id: String)
GET     /document/:id/activity.json                  controllers.document.DocumentController.activityFeed(id: String)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Annotation view resolver service
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /annotation/:id                              controllers.document.annotation.AnnotationController.resolveFromAnnotation(id: java.util.UUID)
GET     /part/:id                                    controllers.document.annotation.AnnotationController.resolveFromPart(id: java.util.UUID)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# JSON API
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# ~~~ Account information ~~~

GET     /api/me                                      controllers.my.account.AccountInfoController.me
GET     /api/account/my                              controllers.my.account.AccountInfoController.getPrivateAccountInfo
GET     /api/account/:username                       controllers.my.account.AccountInfoController.getPublicAccountInfo(username: String)
GET     /api/account/:username/collaborators         controllers.my.account.AccountInfoController.getCollaborators(username: String)

# ~~~ Readme create & delete ~~~

POST    /api/directory/my/readme                     controllers.my.directory.create.CreateController.createReadme(id: java.util.UUID ?= null)
POST    /api/folder/:id/readme                       controllers.my.directory.create.CreateController.createReadme(id: java.util.UUID)   

DELETE  /api/directory/my/readme                     controllers.my.directory.delete.FolderActionsController.deleteReadme(id: java.util.UUID ?= null)
DELETE  /api/folder/:id/readme                       controllers.my.directory.delete.FolderActionsController.deleteReadme(id: java.util.UUID)     

# ~~~ Directory list access ~~~

GET     /api/directory/my                            controllers.my.directory.list.DirectoryController.getMyDirectory(offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID ?= null)
POST    /api/directory/my                            controllers.my.directory.list.DirectoryController.getMyDirectory(offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID ?= null)

GET     /api/directory/my/shared                     controllers.my.directory.list.DirectoryController.getSharedWithMe(offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID ?= null)
POST    /api/directory/my/shared                     controllers.my.directory.list.DirectoryController.getSharedWithMe(offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID ?= null)

GET     /api/directory/my/:folderId                  controllers.my.directory.list.DirectoryController.getMyDirectory(offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID)
POST    /api/directory/my/:folderId                  controllers.my.directory.list.DirectoryController.getMyDirectory(offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID)

GET     /api/directory/my/shared/:folderId           controllers.my.directory.list.DirectoryController.getSharedWithMe(offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID)
POST    /api/directory/my/shared/:folderId           controllers.my.directory.list.DirectoryController.getSharedWithMe(offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID)

GET     /api/directory/:owner                        controllers.my.directory.list.DirectoryController.getAccessibleDocuments(owner: String, offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID ?= null)
POST    /api/directory/:owner                        controllers.my.directory.list.DirectoryController.getAccessibleDocuments(owner: String, offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID ?= null)
GET     /api/directory/:owner/:folderId              controllers.my.directory.list.DirectoryController.getAccessibleDocuments(owner: String, offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID)
POST    /api/directory/:owner/:folderId              controllers.my.directory.list.DirectoryController.getAccessibleDocuments(owner: String, offset: Int ?= 0, size: Int ?= 500, folderId: java.util.UUID)

# ~~~ Create, duplicate, delete & unshare (my shared) operations ~~~

POST    /api/folder                                  controllers.my.directory.create.CreateController.createFolder
POST    /api/clone/document/:id                      controllers.my.directory.create.CreateController.cloneDocument(id: String)

PUT     /api/document/bulk                           controllers.my.directory.update.UpdateController.bulkUpdateDocuments
PUT     /api/document/:id                            controllers.my.directory.update.UpdateController.updateDocument(id: String)
PUT     /api/folder/bulk                             controllers.my.directory.update.UpdateController.bulkUpdateFolders
PUT     /api/folder/:id                              controllers.my.directory.update.UpdateController.updateFolder(id: java.util.UUID)

DELETE  /api/document/bulk                           controllers.my.directory.delete.DocumentActionsController.bulkDeleteDocuments
DELETE  /api/document/:id                            controllers.my.directory.delete.DocumentActionsController.deleteDocument(id: String)
DELETE  /api/shared/document/bulk                    controllers.my.directory.delete.DocumentActionsController.bulkUnshareDocuments
DELETE  /api/shared/document/:id                     controllers.my.directory.delete.DocumentActionsController.unshareDocument(id: String)

DELETE  /api/folder/bulk                             controllers.my.directory.delete.FolderActionsController.bulkDeleteFolders
DELETE  /api/folder/:id                              controllers.my.directory.delete.FolderActionsController.deleteFolder(id: java.util.UUID)
DELETE  /api/shared/folder/bulk                      controllers.my.directory.delete.FolderActionsController.bulkUnshareFolders
DELETE  /api/shared/folder/:id                       controllers.my.directory.delete.FolderActionsController.unshareFolder(id: java.util.UUID)

# ~~~ Bulk sharing ~~~

GET     /api/sharing/search                          controllers.my.sharing.SharingController.searchUsers(q: String)
GET     /api/sharing/folders/:id/visibility          controllers.my.sharing.SharingController.getFolderVisibility(id: java.util.UUID)
POST    /api/sharing/folders/visibility              controllers.my.sharing.SharingController.setFolderVisibility
GET     /api/sharing/folders/:id/collaborators       controllers.my.sharing.SharingController.getFolderCollaborators(id: java.util.UUID)
POST    /api/sharing/folders/collaborator            controllers.my.sharing.SharingController.addFolderCollaborator
DELETE  /api/sharing/folders/collaborator            controllers.my.sharing.SharingController.removeFolderCollaborator

# ~~~ Search ~~~

GET     /api/search                                  controllers.my.directory.search.SearchController.search
POST    /api/search                                  controllers.my.directory.search.SearchController.search

# ~~~ Announcements ~~~

GET     /api/announcements/my/latest                 controllers.api.message.AnnouncementAPIController.myLatest
PUT     /api/announcements/:id                       controllers.api.message.AnnouncementAPIController.confirm(id: java.util.UUID)

POST    /api/send-message                            controllers.api.message.AnnouncementAPIController.sendMessage

# ~~~ Clone network ~~~

GET     /api/document/:id/network                    controllers.api.network.NetworkAPIController.getNetwork(id: String)
POST    /api/document/:id/merge                      controllers.api.network.NetworkAPIController.mergeAnnotations(id: String, from: String)

# ~~~ Similarity search ~~~

GET     /api/similar/:id                             controllers.api.similarity.SimilarityAPIController.getSimilar(id: String)

# ~~~ Annotations ~~~

POST    /api/annotation                              controllers.api.annotation.AnnotationAPIController.createAnnotation

GET     /api/annotation/:id.jpg                      controllers.api.annotation.AnnotationAPIController.getImage(id: java.util.UUID)
GET     /api/annotation/:id                          controllers.api.annotation.AnnotationAPIController.getAnnotation(id: java.util.UUID, context: Boolean ?= false)

POST    /api/annotation/bulk                         controllers.api.annotation.AnnotationAPIController.bulkUpsert
DELETE  /api/annotation/bulk                         controllers.api.annotation.AnnotationAPIController.bulkDelete
DELETE  /api/annotation/:id                          controllers.api.annotation.AnnotationAPIController.deleteAnnotation(id: java.util.UUID)

GET     /api/document/:id/annotations                controllers.api.annotation.AnnotationAPIController.listAnnotationsInDocument(id: String)
GET     /api/document/:id/part/:part/annotations     controllers.api.annotation.AnnotationAPIController.listAnnotationsInPart(id: String, part: Int)

GET     /api/document/:id/places/search              controllers.api.entity.PlaceAPIController.searchPlacesInDocument(q: String, id: String, offset: Int ?= 0, size: Int ?= 20)
GET     /api/document/:id/places                     controllers.api.entity.PlaceAPIController.listPlacesInDocument(id: String, offset: Int ?= 0, size: Int ?= 0)

# ~~~ Contributions ~~~

GET     /api/document/:id/contributions              controllers.api.contribution.ContributionAPIController.getDocumentStats(id: String)
GET     /api/document/:id/contributions/count        controllers.api.contribution.ContributionAPIController.countContributionsSince(id: String, since: String)

# ~~~ Authorities ~~~ 

GET     /api/authorities/gazetteers                  controllers.api.entity.AuthoritiesAPIController.listGazetteers

# ~~~ Entities ~~~

GET     /api/place/search                            controllers.api.entity.PlaceAPIController.searchPlaces(q: String, offset: Int ?= 0, size: Int ?= 20, latlng: Option[String] ?= None, authorities: Option[String] ?= None)
GET     /api/place/:uri                              controllers.api.entity.PlaceAPIController.findPlaceByURI(uri: String)

# ~~~ Tasks ~~~

POST    /api/job                                     controllers.api.task.TaskAPIController.spawnJob
GET     /api/job                                     controllers.api.task.TaskAPIController.progressByDocument(id: String)
GET     /api/job/:id                                 controllers.api.task.TaskAPIController.getJobProgress(id: java.util.UUID)

# ~~~ Plugins ~~~
GET     /api/plugins/ner                             controllers.api.plugin.PluginAPIController.listNERPlugins
GET     /api/plugins/js/:ext/:id.js                  controllers.api.plugin.PluginAPIController.loadPlugin(ext: String, id: String)
GET     /api/plugins/js/:ext/:id.css                 controllers.api.plugin.PluginAPIController.loadCSS(ext: String, id: String)

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Personal space - settings
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /settings/account                            controllers.my.settings.AccountSettingsController.index
POST    /settings/account                            controllers.my.settings.AccountSettingsController.updateAccountSettings
DELETE  /settings/account                            controllers.my.settings.AccountSettingsController.deleteAccount
GET     /settings/password                           controllers.my.settings.PasswordSettingsController.index
POST    /settings/password                           controllers.my.settings.PasswordSettingsController.updatePassword
GET     /settings/restore                            controllers.my.settings.RestoreController.index
POST    /settings/restore                            controllers.my.settings.RestoreController.restore

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Personal space - upload
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

POST    /my/upload                                   controllers.my.directory.create.CreateController.initUpload()
POST    /my/upload/:id/file                          controllers.my.directory.create.CreateController.storeFilepart(id: Int)
POST    /my/upload/:id/finalize                      controllers.my.directory.create.CreateController.finalizeUpload(id: Int, folder: Option[java.util.UUID])

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Application root
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /sitemap.txt                                 controllers.landing.LandingController.sitemap
GET     /robots.txt                                  controllers.landing.LandingController.robots
GET     /stats.json                                  controllers.landing.LandingController.getStats
GET     /swagger.json                                controllers.landing.LandingController.swaggerConfig
GET     /                                            controllers.landing.LandingController.index

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Personal space root
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GET     /my                                          controllers.my.WorkspaceController.my
GET     /:username                                   controllers.my.WorkspaceController.workspace(username: String)
GET     /:username/activity.json                     controllers.my.WorkspaceController.activityFeed(username: String)