AWSTemplateFormatVersion: '2010-09-09'
Description: Template for API Gateway and EventBridge

Resources:

  APIGatewayRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
      Policies:
        - PolicyName: PushToEventBridge
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - events:PutEvent
                  - events:PutEvents
                Resource: 
                  - !GetAtt SurveyEventBus.Arn

  SurveyEventBus:
    Type: AWS::Events::EventBus
    Properties:
      Name: !Sub "${AWS::StackName}-SurveyEB"

  SurveyPublicApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      EndpointConfiguration:
        Types:
          - REGIONAL
      Name: !Sub ${AWS::StackName}-SurveyApi

  SurveysResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      ParentId: !GetAtt SurveyPublicApi.RootResourceId
      PathPart: surveys
      RestApiId: !Ref SurveyPublicApi
  
  SpecificSurveyResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      ParentId: !Ref SurveysResource
      PathPart: mysurveyid
      RestApiId: !Ref SurveyPublicApi
  
  SurveyResponsesResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      ParentId: !Ref SpecificSurveyResource
      PathPart: responses
      RestApiId: !Ref SurveyPublicApi

  SendSurveyResponseMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      AuthorizationType: NONE
      HttpMethod: POST
      MethodResponses:
        - StatusCode: 200
          ResponseModels:
            application/json: Empty
          ResponseParameters:
            method.response.header.Access-Control-Allow-Headers: true
            method.response.header.Access-Control-Allow-Methods: true
            method.response.header.Access-Control-Allow-Origin: true
      RequestParameters: 
        method.request.header.X-Amz-Target: false
        method.request.header.Content-Type: false
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS
        Credentials: !GetAtt APIGatewayRole.Arn 
        Uri: !Sub arn:aws:apigateway:${AWS::Region}:events:action/PutEvents
        PassthroughBehavior: NEVER
        RequestTemplates: 
          application/json: !Sub 
            - |- 
              #set($context.requestOverride.header.X-Amz-Target = "AWSEvents.PutEvents")
              #set($context.requestOverride.header.Content-Type = "application/x-amz-json-1.1")            
              #set($inputRoot = $input.json('$')) 
              { 
                "Entries": [
                  {
                    "Detail": "$util.escapeJavaScript($inputRoot).replaceAll("\\'","'")",
                    "DetailType": "SurveyResponseReceived",
                    "EventBusName": "${EventBusName}",
                    "Source":"SurveyResponse"
                  }
                ]
              }
            - { EventBusName: !Ref SurveyEventBus }
        IntegrationResponses:
          - StatusCode: 200
            ResponseParameters:
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
              method.response.header.Access-Control-Allow-Methods: "'OPTIONS,POST'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
            ResponseTemplates: 
              application/json: |- 
                #set($val = $input.path('$.Entries[0].EventId'))
                {
                  "response": "$val"
                }
      RequestModels:
        application/json: !Ref MySurveyIdResponseBodyModel
      RequestValidatorId: !Ref MySurveyIdResponseRequestValidator
      ResourceId: !Ref SurveyResponsesResource
      RestApiId: !Ref SurveyPublicApi

  SendSurveyResponseCORSMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      AuthorizationType: NONE
      HttpMethod: OPTIONS
      MethodResponses:
        - StatusCode: 200
          ResponseModels:
            application/json: Empty
          ResponseParameters:
            method.response.header.Access-Control-Allow-Headers: true
            method.response.header.Access-Control-Allow-Methods: true
            method.response.header.Access-Control-Allow-Origin: true
      RequestParameters: {}
      Integration:
        Type: MOCK
        PassthroughBehavior: WHEN_NO_MATCH
        RequestTemplates: 
          application/json:  "{\"statusCode\": 200}"
        IntegrationResponses:
          - StatusCode: 200
            ResponseParameters:
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
              method.response.header.Access-Control-Allow-Methods: "'OPTIONS,POST'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
      ResourceId: !Ref SurveyResponsesResource
      RestApiId: !Ref SurveyPublicApi

  MySurveyIdResponseBodyModel:
    Type: 'AWS::ApiGateway::Model'
    Properties:
      RestApiId: !Ref SurveyPublicApi
      ContentType: application/json
      Description: Schema for MySurveyId responses
      Name: MySurveyIdResponseBody
      Schema:
        $schema: 'http://json-schema.org/draft-04/schema#'
        title: MySurveyIdResponseBody
        type: object
        properties:
          role:
            type: string
            enum:
              - c
              - sc
              - lead
              - m+
              - customer
          balls:
            type: integer
            minimum: 100
            maximum: 1000000
            multipleOf: 100
          cups:
            type: integer
            minimum: 0
            maximum: 1000
        required:
          - role
          - balls
          - cups

  MySurveyIdResponseRequestValidator:
    Type: AWS::ApiGateway::RequestValidator
    Properties:
      RestApiId: !Ref SurveyPublicApi
      ValidateRequestBody: true
      ValidateRequestParameters: false

  SurveyPublicApiDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn:
      - SendSurveyResponseMethod
      - SendSurveyResponseCORSMethod
    Properties:
      RestApiId: !Ref SurveyPublicApi
      StageName: v1

Outputs:
  APIEndpoint:
    Description: Survey response API endpoint
    Value: !Sub https://${SurveyPublicApi}.execute-api.${AWS::Region}.amazonaws.com/v1/surveys/mysurveyid/responses
  EventBus:
    Description: EventBridge Bus
    Value: !Ref SurveyEventBus
