swagger: "2.0"
info:
  title: Community Detection microservice
  description: This is the documentation for the community detection microservice.
  version: "1.0.0"

consumes:
  - "application/json"
produces:
  - "application/json"

basePath: "/api"

paths:
  /debug:
    post:
      operationId: "routes.debug.echo"
      tags:
        - "Echo"
      summary: "Echo function for debugging purposes"
      description: "Echoes the input back to the caller."
      parameters:
        - in: body
          name: "Object"
          required: true
          schema:
            type: object
      responses:
        200:
          description: "Successful echo of request data"
          
# Locations
# TODO remove
  /locations:
    post:
        operationId: "routes.location.post"
        tags:
          - "Locations"
        summary: "Add new location data"
        parameters:
          - in: body 
            name: "Location"
            description: "The location data to be added"
            required: true
            schema:
              $ref: "#/definitions/Location"
        responses:
          201:
            description: "Successful operation"
          400:
            description: "Invalid input"
    get:
        operationId: "routes.location.get"
        tags:
            - "Locations"
        summary: "Get location data"
        parameters: []
        responses:
          200:
            description: "Successful operation"
            schema:
              $ref: "#/definitions/LocationCollection"
  
  /location-collections:
    post:
        operationId: "routes.location.post_many"
        tags:
          - "Locations"
        summary: "Add new location data collection"
        parameters:
          - in: body 
            name: "Locations"
            description: "The location data collection to be added"
            required: true
            schema:
                $ref: "#/definitions/LocationCollection"
        responses:
          201:
            description: "Successful operation"
          400:
            description: "Invalid input"

#region Layers

  /layers:
    post:
        operationId: "routes.layers.post"
        tags:
          - "Layers"
        summary: "Add a new layer [TODO: or overwrite an existing one]"
        parameters:
          - in: body 
            name: "layer"
            description: "The layer data to be added"
            required: true
            schema:
                $ref: "#/definitions/Layer-UpperCase"
        responses:
            201:
                description: "Successful operation"
            400:
                description: "Invalid input"
    get:
        operationId: "routes.layers.get"
        tags:
            - "Layers"
        summary: "Get all layer data"
        parameters: []
        responses:
            200:
                description: "Successful operation"
                schema:
                    $ref: "#/definitions/LayerCollection"
    
  /layers/{name}:
    get:
        operationId: "routes.layers.get_by_name"
        tags:
            - "Layers"
        summary: "Get single layer data"
        parameters: 
          - name: "name"
            in: "path"
            description: "Name of the requested layer"
            required: true
            type: "string"
        responses:
            200:
                description: "Successful operation"
                schema: 
                    $ref: "#/definitions/Layer"
            404:
                description: "Layer not found"

  /layers/{name}/nodes:
    get:
        operationId: "routes.layers.get_nodes"
        tags:
            - "Layers"
        summary: "Get all individual nodes for the layer"
        parameters: 
          - name: "name"
            in: "path"
            description: "Name of the layer"
            required: true
            type: "string"
        responses:
            200:
                description: "Successful operation"
                schema: 
                    $ref: "#/definitions/NodeCollection"
            404:
                description: "Layer not found"
    post:
        operationId: "routes.layers.post_nodes"
        tags:
            - "Layers"
        summary: "Adds a single or multiple nodes to the layer"
        parameters: 
          - name: "name"
            in: "path"
            description: "Name of the layer"
            required: true
            type: "string"
          - name: "node"
            in: body 
            description: "The node(s) to be added"
            required: true
            schema:
                $ref: "#/definitions/NodeCollection"
        responses:            
            201:
                description: "Successful operation"
            400:
                description: "Invalid input"

  /layers/{name}/clusters:
    get:
        operationId: "routes.clustersets.get_by_name2"
        tags:
            - "Layers"
        summary: "Get all clusters for the layer"
        parameters: 
          - name: "name"
            in: "path"
            description: "Name of the layer"
            required: true
            type: "string"
        responses:
            200:
                description: "Successful operation"
                schema: 
                    $ref: "#/definitions/ClusterCollection"
            404:
                description: "Layer not found"

  /layers/{name}/timeslices:
    get:
        operationId: "routes.timeslices.get_by_name2"
        tags:
            - "Layers"
        summary: "Get all timeslices for the layer"
        parameters: 
          - name: "name"
            in: "path"
            description: "Name of the layer"
            required: true
            type: "string"
        responses:
            200:
                description: "Successful operation"
                schema: 
                    $ref: "#/definitions/TimeSliceCollection"
            404:
                description: "Layer not found"
#endregion 
                
# Clusters
# TODO remove partially
  /location-clusters:
    get:
        operationId: "routes.cluster.get_locations"
        tags:
            - "Clusters"
        summary: "Get user communities clustered by location"
        parameters: []
        responses:
            200:
                description: "Successful operation"
                schema:
                  $ref: "#/definitions/LocationClusterCollection"

  # /clusters/cluster.png:
  #   get:
  #       operationId: "routes.cluster.get_image"
  #       tags:
  #           - "Clusters"
  #       summary: "Get user communities per date per hour as image"
  #       parameters: []
  #       produces:
  #           - "image/png"
  #       responses:
  #           200:
  #               description: "Successful operation"
  
  /time-clusters:
    get:
        operationId: "routes.cluster.get_times"
        tags:
            - "Clusters"
        summary: "Get user communities clustered by time per hour"
        parameters: []
        responses:
            200:
                description: "Successful operation"
                schema:
                  $ref: "#/definitions/TimeClusterCollection"

  # /agi/clusters/cluster.png:
  #   get:
  #       operationId: "routes.agi_cluster.get_image"
  #       tags:
  #           - "Clusters"
  #       summary: "Get user communities per date per hour from agi data as image"
  #       parameters: []
  #       produces:
  #           - "image/png"
  #       responses:
  #           200:
  #               description: "Successful operation"
          
# TODO remove
  /clustersets:
    get:
        operationId: "routes.clustersets.get"
        tags:
            - "Clusters"
        summary: "Get clustersets for all layers"
        parameters: []
        responses:
            200:
                description: "Successful operation"
                schema:
                    $ref: "#/definitions/ClusterSetCollection"
                    
  /clustersets/names:
    get:
        operationId: "routes.clustersets.get_names"
        tags:
            - "Clusters"
        summary: "Get clusterset names for all layers"
        parameters: []
        responses:
            200:
                description: "Successful operation"
                schema:
                    type: array
                    items:
                        type: string

  /clustersets/{layername}:
    get:
        operationId: "routes.clustersets.get_by_name"
        tags:
            - "Clusters"
        summary: "Get clusterset for layer-name"
        parameters: 
          - name: "layername"
            in: "path"
            description: "Name of the layer to return the clusterset for"
            required: true
            type: "string"
        responses:
            200:
                description: "Successful operation"
                schema:
                    $ref: "#/definitions/ClusterSet"
            404:
                description: "Clusterset not found"


# TODO remove                    
  /user-cluster-graphs:
    get:
        operationId: "routes.user_cluster.get"
        tags:
            - "User Graphs"
        summary: "Get user graphs per layer per cluster"
        parameters: []
        responses:
            200:
                description: "Successful operation"
                schema:
                  $ref: "#/definitions/UserClusterGraphCollection"

# Time slices
  /timeslices:
    get:
        operationId: "routes.timeslices.get"
        tags:
            - "Time Slices"
        summary: "Get all time slices based on individual layers containing clusters with nodes for that time"
        parameters: []
        responses:
            200:
                description: "Successful operation"
                schema:
                    $ref: "#/definitions/TimeSliceCollection"
                
                
  /timeslices/{layername}:
    get:
        operationId: "routes.timeslices.get_by_name"
        tags:
            - "Time Slices"
        summary: "Get all time slices for one layer"
        parameters:
          - name: "layername"
            in: "path"
            description: "Name of the layer to return the time slices for"
            required: true
            type: "string"
        responses:
            200:
                description: "Successful operation"
                schema:
                    $ref: "#/definitions/TimeSliceCollection"
            404:
                description: "No time slices found for layername"

# Function Calls
  /rfc/run:
    post:
        operationId: "routes.functions.run_agi_clustering_and_graph_creation"
        tags:
            - "Remote function calls"
        summary: "Insert locations from AGI, create clusters for starting time and location layers, create graphs for the location clusters"
        parameters: []
        responses:
            204:
                description: "Successful operation"


definitions:
  Location:
    type: "object"
    properties:
      id:
        type: string
      user:
        type: "string"
      latitude:
        type: "number"
        format: float
      longitude:
        type: "number"
        format: float
      timestamp:
        type: "number"

  LocationCollection:
    type: array
    items:
      $ref: "#/definitions/Location"

  Cluster:
    type: object
    properties:
        layer_name:
            type: string
        cluster_label:
            type: number
        nodes:
            type: array
            items: 
                $ref: "#/definitions/Node"
                

  ClusterCollection:
    type: array
    items:
        $ref: "#/definitions/Cluster"

  LocationCluster:
    type: object
    properties:
      id:
        type: string
      cluster_label:
        type: number
      nodes:
        type: array
        items: 
          $ref: "#/definitions/Location"
  
  LocationClusterCollection:
    type: array
    items:
      $ref: "#/definitions/LocationCluster"

  TimeCluster:
    type: object
    properties:
      id:
        type: string
      date:
        type: string
      hour:
        type: number
      cluster_label:
        type: number
      nodes:
        type: array
        items: 
          $ref: "#/definitions/Location"

  TimeClusterCollection:
    type: array
    items:
      $ref: "#/definitions/TimeCluster"

  UserClusterGraph:
    type: object
    properties:
      nodes:
        type: array
        items: 
          type: string
      edges:
        type: array
        items: 
          type: array
          items:
            type: string
          example: 
            - user1
            - user2
            - weight

  UserClusterGraphCollection:
    type: array
    items:
      $ref: "#/definitions/UserClusterGraph"

  Layer-UpperCase:
    type: object
    properties:
        LayerName:
            type: string
        # Nodes:
        #     type: array
        #     items: 
        #         type: object
        Properties:
            type: array
            items: 
                type: string
    
  Layer:
    type: object
    properties:
        layer_name:
            type: string
        # nodes:
        #     type: array
        #     items: 
        #         type: object
        properties:
            type: array
            items: 
                type: string

  LayerCollection:
    type: array
    items:
        $ref: "#/definitions/Layer"

  Node:
    type: object
    example:
        "Finished_time": 1576631193265951
        "Latitude_Destination": -5.973257
        "Longitude_Destination": 37.416316
        "TravelID": "5e57ec9159bc0668543f156a"
        "TravelPrice": 15
        "UniqueID": "a95075f5042b1b27060080156d87fe34ec7e712c5e57ec9159bc0668543f156a"
        "UserID": "a95075f5042b1b27060080156d87fe34ec7e712c"

  NodeCollection:
    type: array
    items: 
        $ref: "#/definitions/Node"
  
  ClusterSet:
    type: object
    properties:
        layer_name: 
            type: string
        clusters:
            type: array
            items: 
                $ref: "#/definitions/Cluster"

  ClusterSetCollection:
    type: array
    items:
      $ref: "#/definitions/ClusterSet"

  TimeSlice:
    type: object
    properties:
        time: 
            type: object
            example: "(2020, 52)"
        layer_name:
            type: string
        clusters:
            type: object
            additionalProperties:
                type: array
                items:
                    type: object
                    properties:
                        UniqueID:
                            type: string
            example:
                "0": 
                    - UniqueID: abc
                    - UniqueID: def
  
  TimeSliceCollection:
    type: array
    items:
        $ref: "#/definitions/TimeSlice"