{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Transform": "AWS::Serverless-2016-10-31",
  "Description": "An AWS Serverless Application.",
  "Parameters": {
    "ConnectionMappingTableName": {
      "Type": "String",
      "Default": "SimpleChatConnections",
      "Description": "The name of the new DynamoDB to store connection identifiers for each connected clients. Minimum 3 characters.",
      "MinLength": "3",
      "MaxLength": "50",
      "AllowedPattern": "^[A-Za-z_]+$"
    }
  },
  "Resources": {
    "ConnectionMappingTable": {
      "Type": "AWS::DynamoDB::Table",
      "Properties": {
        "TableName": {
          "Ref": "ConnectionMappingTableName"
        },
        "AttributeDefinitions": [
          {
            "AttributeName": "connectionId",
            "AttributeType": "S"
          }
        ],
        "KeySchema": [
          {
            "AttributeName": "connectionId",
            "KeyType": "HASH"
          }
        ],
        "BillingMode": "PAY_PER_REQUEST"
      }
    },
    "OnConnectFunction": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "Handler": "BlueprintBaseName.1::BlueprintBaseName._1.Functions::OnConnectHandler",
        "Runtime": "dotnetcore3.1",
        "CodeUri": "",
        "MemorySize": 256,
        "Timeout": 30,
        "Role": null,
        "Policies": [
          {
            "DynamoDBCrudPolicy": {
              "TableName": {
                "Ref": "ConnectionMappingTableName"
              }
            }
          }
        ],
        "Environment": {
          "Variables": {
            "TABLE_NAME": {
              "Ref": "ConnectionMappingTableName"
            }
          }
        }
      }
    },
    "OnDisconnectFunction": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "Handler": "BlueprintBaseName.1::BlueprintBaseName._1.Functions::OnDisconnectHandler",
        "Runtime": "dotnetcore3.1",
        "CodeUri": "",
        "MemorySize": 256,
        "Timeout": 30,
        "Role": null,
        "Policies": [
          {
            "DynamoDBCrudPolicy": {
              "TableName": {
                "Ref": "ConnectionMappingTableName"
              }
            }
          }
        ],
        "Environment": {
          "Variables": {
            "TABLE_NAME": {
              "Ref": "ConnectionMappingTableName"
            }
          }
        }
      }
    },
    "SendMessageFunction": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "Handler": "BlueprintBaseName.1::BlueprintBaseName._1.Functions::SendMessageHandler",
        "Runtime": "dotnetcore3.1",
        "CodeUri": "",
        "MemorySize": 256,
        "Timeout": 30,
        "Role": null,
        "Policies": [
          {
            "DynamoDBCrudPolicy": {
              "TableName": {
                "Ref": "ConnectionMappingTableName"
              }
            }
          },
          {
            "Statement": {
              "Effect": "Allow",
              "Action": "execute-api:ManageConnections",
              "Resource": "arn:aws:execute-api:*:*:*/@connections/*"
            }
          }
        ],
        "Environment": {
          "Variables": {
            "TABLE_NAME": {
              "Ref": "ConnectionMappingTableName"
            }
          }
        }
      }
    },
    "SimpleChatWebSocketApi": {
      "Type": "AWS::ApiGatewayV2::Api",
      "Properties": {
        "Name": "SimpleChatWebSocket",
        "ProtocolType": "WEBSOCKET",
        "RouteSelectionExpression": "$request.body.message"
      }
    },
    "ConnectRoute": {
      "Type": "AWS::ApiGatewayV2::Route",
      "Properties": {
        "ApiId": {
          "Ref": "SimpleChatWebSocketApi"
        },
        "RouteKey": "$connect",
        "AuthorizationType": "NONE",
        "OperationName": "ConnectRoute",
        "Target": {
          "Fn::Join": [
            "/",
            [
              "integrations",
              {
                "Ref": "ConnectInteg"
              }
            ]
          ]
        }
      }
    },
    "ConnectInteg": {
      "Type": "AWS::ApiGatewayV2::Integration",
      "Properties": {
        "ApiId": {
          "Ref": "SimpleChatWebSocketApi"
        },
        "IntegrationType": "AWS_PROXY",
        "IntegrationUri": {
          "Fn::Sub": [
            "arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${function}/invocations",
            {
              "region": {
                "Ref": "AWS::Region"
              },
              "function": {
                "Fn::GetAtt": [
                  "OnConnectFunction",
                  "Arn"
                ]
              }
            }
          ]
        }
      }
    },
    "DisconnectRoute": {
      "Type": "AWS::ApiGatewayV2::Route",
      "Properties": {
        "ApiId": {
          "Ref": "SimpleChatWebSocketApi"
        },
        "RouteKey": "$disconnect",
        "AuthorizationType": "NONE",
        "OperationName": "ConnectRoute",
        "Target": {
          "Fn::Join": [
            "/",
            [
              "integrations",
              {
                "Ref": "DisconnectInteg"
              }
            ]
          ]
        }
      }
    },
    "DisconnectInteg": {
      "Type": "AWS::ApiGatewayV2::Integration",
      "Properties": {
        "ApiId": {
          "Ref": "SimpleChatWebSocketApi"
        },
        "IntegrationType": "AWS_PROXY",
        "IntegrationUri": {
          "Fn::Sub": [
            "arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${function}/invocations",
            {
              "region": {
                "Ref": "AWS::Region"
              },
              "function": {
                "Fn::GetAtt": [
                  "OnDisconnectFunction",
                  "Arn"
                ]
              }
            }
          ]
        }
      }
    },
    "SendMessageRoute": {
      "Type": "AWS::ApiGatewayV2::Route",
      "Properties": {
        "ApiId": {
          "Ref": "SimpleChatWebSocketApi"
        },
        "RouteKey": "sendmessage",
        "AuthorizationType": "NONE",
        "OperationName": "ConnectRoute",
        "Target": {
          "Fn::Join": [
            "/",
            [
              "integrations",
              {
                "Ref": "SendMessageInteg"
              }
            ]
          ]
        }
      }
    },
    "SendMessageInteg": {
      "Type": "AWS::ApiGatewayV2::Integration",
      "Properties": {
        "ApiId": {
          "Ref": "SimpleChatWebSocketApi"
        },
        "IntegrationType": "AWS_PROXY",
        "IntegrationUri": {
          "Fn::Sub": [
            "arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${function}/invocations",
            {
              "region": {
                "Ref": "AWS::Region"
              },
              "function": {
                "Fn::GetAtt": [
                  "SendMessageFunction",
                  "Arn"
                ]
              }
            }
          ]
        }
      }
    },
    "Deployment": {
      "Type": "AWS::ApiGatewayV2::Deployment",
      "DependsOn": [
        "ConnectRoute",
        "SendMessageRoute",
        "DisconnectRoute"
      ],
      "Properties": {
        "ApiId": {
          "Ref": "SimpleChatWebSocketApi"
        }
      }
    },
    "Stage": {
      "Type": "AWS::ApiGatewayV2::Stage",
      "Properties": {
        "ApiId": {
          "Ref": "SimpleChatWebSocketApi"
        },
        "DeploymentId": {
          "Ref": "Deployment"
        },
        "StageName": "Prod"
      }
    },
    "OnConnectPermission": {
      "Type": "AWS::Lambda::Permission",
      "DependsOn": [
        "OnConnectFunction",
        "SimpleChatWebSocketApi"
      ],
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Ref": "OnConnectFunction"
        },
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "OnDisconnectPermission": {
      "Type": "AWS::Lambda::Permission",
      "DependsOn": [
        "OnDisconnectFunction",
        "SimpleChatWebSocketApi"
      ],
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Ref": "OnDisconnectFunction"
        },
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "SendMessagePermission": {
      "Type": "AWS::Lambda::Permission",
      "DependsOn": [
        "SendMessageFunction",
        "SimpleChatWebSocketApi"
      ],
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Ref": "SendMessageFunction"
        },
        "Principal": "apigateway.amazonaws.com"
      }
    }
  },
  "Outputs": {
    "WebSocketURI": {
      "Value": {
        "Fn::Join": [
          "",
          [
            "wss://",
            {
              "Ref": "SimpleChatWebSocketApi"
            },
            ".execute-api.",
            {
              "Ref": "AWS::Region"
            },
            ".amazonaws.com/",
            {
              "Ref": "Stage"
            }
          ]
        ]
      },
      "Description": "The WSS Protocol URI to connect to"
    }
  }
}