AWSTemplateFormatVersion: 2010-09-09
Description: >
  "Get Point of Interest using Location Service in Amazon Connect"

Mappings:
  FunctionMap:
      Configuration:
          S3Bucket: "mytestblog"
          S3Key: "custom-ccp-portal/"



####################################################################################
# Parameters:
####################################################################################

Parameters:
#  RegionName:
#    Type: String
#    Description: Region where Amazon Connect is Running

  CustomCCPS3BucketSourceCode:
    Type: String
    AllowedPattern: '(?=^.{3,63}$)(?!^(\d+\.)+\d+$)(^(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])$)'
    ConstraintDescription: 'Invalid S3 Bucket name'
    Description: Enter the (globally unique) name you would like to use for the Amazon S3 bucket where Website source code will be copied from

  CustomCCPS3BucketForWebSite:
    Type: String
    AllowedPattern: '(?=^.{3,63}$)(?!^(\d+\.)+\d+$)(^(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])$)'
    ConstraintDescription: 'Invalid S3 Bucket name'
    Description: Enter the (globally unique) name you would like to use for the Amazon S3 bucket where we will store the website assets and the sample contact flow. This template will fail to deploy if the bucket name you chose is currently in use.

  instanceIdParam:
    Type: String
    AllowedPattern: '\w{8}-\w{4}-\w{4}-\w{4}-\w{12}'
    ConstraintDescription: "Invalid Amazon Connect instance Id"
    Description: Amazon Connect Instance ID (Ensure you it is entered accurately in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). Must be in this account and same region where this stack is.

  instanceNameParam:
    Type: String
    ConstraintDescription: "Invalid Amazon Connect instance alias"
    Description: Amazon Connect Instance Alias (Ensure you it is entered accurately as configured under Amazon Connect Service ).

  inputMapProviderName:
    AllowedValues:
    - Here
    - Esri
    Type: String
    Default: Here
    Description: Map Provider Name. Valid values are -  Here and Esri


Outputs:
  CloudfrontEndpoint:
    Description: Endpoint for Cloudfront distribution
    Value: !Join
      - ''
      - - 'https://'
        - !GetAtt [CustomCCPCloudFrontDistribution, DomainName]
        - '/agentDesktop.html'



Resources:

  CloudWatchRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
            Action: 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - >-
          arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs
  Account:
    Type: 'AWS::ApiGateway::Account'
    Properties:
      CloudWatchRoleArn: !GetAtt
        - CloudWatchRole
        - Arn

  createWebSiteS3Bucket:
      Type: 'AWS::S3::Bucket'
      Properties:
          BucketName: !Ref CustomCCPS3BucketForWebSite
          PublicAccessBlockConfiguration:
              BlockPublicAcls: False
              BlockPublicPolicy: False
              IgnorePublicAcls: False
              RestrictPublicBuckets: False
          WebsiteConfiguration:
              IndexDocument: agentDesktop.html
              ErrorDocument: error.html
          OwnershipControls:
              Rules:
                - ObjectOwnership: BucketOwnerPreferred

  CustomCCPs3BucketPolicy:
      Type: AWS::S3::BucketPolicy
      DependsOn:
          - CustomCCPCloudFrontDistributionAccessIdentity
      Properties:
          Bucket: !Ref createWebSiteS3Bucket
          PolicyDocument:
              Statement:
                  -
                      Action:
                          - "s3:GetObject"
                      Effect: "Allow"
                      Principal:
                          CanonicalUser:
                              Fn::GetAtt: [ CustomCCPCloudFrontDistributionAccessIdentity , S3CanonicalUserId ]
                      Resource:
                          !Sub ${createWebSiteS3Bucket.Arn}/CCP/*

  CustomCCPCloudFrontDistributionAccessIdentity:
      Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
      Properties:
        CloudFrontOriginAccessIdentityConfig:
          Comment: 'CloudFront endpoint for Custom CCP'

  CustomCCPCloudFrontDistribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          Origins:
          - DomainName:
              !Join
                  - ''
                  - - !Ref CustomCCPS3BucketForWebSite
                    - .s3.amazonaws.com
            Id: !Ref CustomCCPS3BucketForWebSite
            OriginPath: '/CCP'
            S3OriginConfig:
              OriginAccessIdentity:
                  !Join
                      - ''
                      - - 'origin-access-identity/cloudfront/'
                        - !Ref CustomCCPCloudFrontDistributionAccessIdentity
          Enabled: 'true'
          Logging:
              Bucket: !GetAtt createWebSiteS3Bucket.DomainName
              Prefix: 'logs/'
              IncludeCookies: 'true'
          Comment: CloudFront for Custom CCP AdminDesktop
          DefaultRootObject: agentDesktop.html
          DefaultCacheBehavior:
              AllowedMethods:
                  - DELETE
                  - GET
                  - HEAD
                  - OPTIONS
                  - PATCH
                  - POST
                  - PUT
              TargetOriginId: !Ref CustomCCPS3BucketForWebSite
              ForwardedValues:
                  QueryString: true
                  Cookies:
                      Forward: all
              ViewerProtocolPolicy: redirect-to-https


  CustomCCPWebSiteCreatorRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          -
            Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: /
      ManagedPolicyArns:
        - !Ref CustomCCPWebSiteCreatorPolicy

  CustomCCPWebSiteCreatorPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: !Sub ${AWS::StackName}-website-creator-policy
      Path: /
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          -
            Effect: "Allow"
            Action:
              - 'logs:CreateLogGroup'
              - 'logs:CreateLogStream'
              - 'logs:PutLogEvents'
            Resource:
              - !Sub "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"
          -
            Effect: "Allow"
            Action:
              - "s3:PutObject"
              - "s3:GetObject"
              - "s3:PutObjectAcl"
            Resource:
              -  !Join
                  - ''
                  - - 'arn:'
                    - !Ref 'AWS::Partition'
                    - ':s3:::'
                    - !Ref CustomCCPS3BucketForWebSite
                    - '/*'
          -
            Effect: "Allow"
            Action:
              - "s3:PutBucketPublicAccessBlock"
            Resource:
              -  !Join
                  - ''
                  - - 'arn:'
                    - !Ref 'AWS::Partition'
                    - ':s3:::'
                    - !Ref CustomCCPS3BucketForWebSite
          -
            Effect: "Allow"
            Action:
              - "s3:GetObject"
            Resource:
              -  !Join
                  - ''
                  - - 'arn:'
                    - !Ref 'AWS::Partition'
                    - ':s3:::'
                    - !Ref CustomCCPS3BucketSourceCode
                    - '/*'


  webSiteCreator:
    Type: "AWS::Lambda::Function"
    Properties:
      Description:  >
          AWS Lambda Function that will create the website and upload it to the S3 bucket
      Handler: "index.handler"
      Role: !GetAtt CustomCCPWebSiteCreatorRole.Arn
      Runtime: "nodejs18.x"
      MemorySize: 256
      Timeout: 120
      Code:
          S3Bucket: !Ref CustomCCPS3BucketSourceCode
          S3Key: !Join [ "", ['custom-ccp-portal', '/POIResultsUI.zip'] ]


  invokeWebSiteCreator:
      Type: Custom::CreateWebSite
      DependsOn: createWebSiteS3Bucket
      Properties:
          ServiceToken:  !GetAtt webSiteCreator.Arn
          customAction: configureWebsite
          Region: !Ref AWS::Region
          sourceS3Bucket: !Ref CustomCCPS3BucketSourceCode
          sourceS3key: "custom-ccp-portal"
          destS3Bucket: !Ref CustomCCPS3BucketForWebSite
          destS3KeyPrefix: CCP
          instanceID: !Ref instanceIdParam
          instanceName: !Ref instanceNameParam
          gatewayAPI: !Ref GetPoiDetailsApi
          manifestLocation: "custom-ccp-portal/web-site-manifest.json"
          identityPoolId: !Ref CognitoIdentityPoolForMap
          locationMapName: !Ref LocationMap


  LocationMap:
    Type: AWS::Location::Map
    Properties:
      Configuration:
        Style: VectorEsriStreets
      Description: Amazon Location Service Map Name
      MapName: !Sub ${AWS::StackName}-map
      PricingPlan: RequestBasedUsage

  MapIndex:
    Type: AWS::Location::PlaceIndex
    Properties:
      DataSource: !Ref inputMapProviderName
      Description: Map Index Name
      IndexName: !Sub ${AWS::StackName}-map_index
      PricingPlan: RequestBasedUsage

  RouteCalculator:
    Type: AWS::Location::RouteCalculator
    Properties:
      CalculatorName: !Sub ${AWS::StackName}-route_calculator
      DataSource: !Ref inputMapProviderName
      Description: Route Calculator
      PricingPlan: RequestBasedUsage

  CognitoMapsForCCPAuthRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Federated: cognito-identity.amazonaws.com
            Action:
              - 'sts:AssumeRoleWithWebIdentity'
            Condition:
              StringEquals:
                "cognito-identity.amazonaws.com:aud": !Ref CognitoIdentityPoolForMap
              "ForAnyValue:StringLike":
                "cognito-identity.amazonaws.com:amr": authenticated
      ManagedPolicyArns:
        - !Ref CognitoMapsForCCPAuthPolicy

  CognitoMapsForCCPAuthPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: !Sub ${AWS::StackName}-cognito_maps_for_ccp_auth-policy
      Path: /
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - mobileanalytics:PutEvents
              - cognito-sync:*
              - cognito-identity:*
            Resource: "*"

  CognitoMapsForCCPUnAuthRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Federated: cognito-identity.amazonaws.com
            Action:
              - 'sts:AssumeRoleWithWebIdentity'
            Condition:
              StringEquals:
                "cognito-identity.amazonaws.com:aud": !Ref CognitoIdentityPoolForMap
              "ForAnyValue:StringLike":
                "cognito-identity.amazonaws.com:amr": unauthenticated
      ManagedPolicyArns:
        - !Ref CognitoMapsForCCPUnAuthPolicy

  CognitoMapsForCCPUnAuthPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: !Sub ${AWS::StackName}-cognito_maps_for_ccp_unauth-policy
      Path: /
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - geo:GetMapStyleDescriptor
              - geo:GetMapGlyphs
              - geo:GetMapSprites
              - geo:GetMapTile

            Resource: !Join
              - ''
              - - 'arn:aws:geo:'
                - !Ref 'AWS::Region'
                - ':'
                - !Ref 'AWS::AccountId'
                - ':map/'
                - !Ref LocationMap
            Condition:
              StringLike:
                'aws:Referer':
                  - '*'



  CognitoIdentityPoolForMap:
    Type: AWS::Cognito::IdentityPool
    Properties:
      AllowUnauthenticatedIdentities: true
      IdentityPoolName: !Sub ${AWS::StackName}-cognito_identity

  CognitoIdentityPoolRoleAttachment:
    Type: AWS::Cognito::IdentityPoolRoleAttachment
    Properties:
      IdentityPoolId: !Ref CognitoIdentityPoolForMap
      Roles:
        "authenticated": !GetAtt CognitoMapsForCCPAuthRole.Arn
        "unauthenticated": !GetAtt CognitoMapsForCCPUnAuthRole.Arn


  poiDataDynamoDBTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: poi_label
        AttributeType: S
      KeySchema:
      - AttributeName: poi_label
        KeyType: HASH
      BillingMode: PAY_PER_REQUEST
      TableName:  !Sub ${AWS::StackName}-poi_of_interest

  populatePoiDetails:
    Type: 'AWS::Lambda::Function'
    Properties:
      Environment:
        Variables:
          PoiTableName: !Select [1, !Split ['/', !GetAtt poiDataDynamoDBTable.Arn]]
      Handler: index.lambda_handler
      Timeout: 30
      Runtime: python3.8
      Role: !GetAtt BlogDDBLambdaRole.Arn
      Code:
        ZipFile: !Sub |
          import json
          import boto3
          import os
          import cfnresponse

          ddb_table = os.environ['PoiTableName']

          dynamodb = boto3.client('dynamodb')

          def lambda_handler(event, context):
            try:
              print (event)
              print (context)
              i=0
              while i < 10:
                  telephone='999-525-300'+ str(i)
                  item = {
                      'poi_label' : {'S': str(i)},
                      'hours_of_operation' : {'S': 'Monday:8am-5pm, Tuesday:8am-5pm, Wednesday:8am-5pm, Thursday:8am-5pm, Saturday:Closed, Sunday:Closed'},
                      'telephone_number': {'S': telephone}
                  }

                  response = dynamodb.put_item(
                      TableName = ddb_table,
                      Item = item)
                  print ("response")
                  i=i+1
              cfnresponse.send(event, context, "SUCCESS", {
                    "Message": "DynamoDB Population is Successful!"})
            except Exception as err:
                  cfnresponse.send(event, context, "FAILED", {
                    "Message": str(err)})


  invokePopulatePoiDetails:
      Type: Custom::PopulatePoiDetails
      DependsOn:
        - populatePoiDetails
        - poiDataDynamoDBTable
      Properties:
          ServiceToken:  !GetAtt populatePoiDetails.Arn
          PoiTableName: !Select [1, !Split ['/', !GetAtt poiDataDynamoDBTable.Arn]]


  GetPoiDetails:
    Type: 'AWS::Lambda::Function'
    Properties:
      Environment:
        Variables:
          TargetIndexName: !Ref MapIndex
          PoiTableName: !Select [1, !Split ['/', !GetAtt poiDataDynamoDBTable.Arn]]
          RouteCalculatorName: !Ref RouteCalculator
      Handler: index.lambda_handler
      Timeout: 30
      Runtime: python3.9
      Role: !GetAtt BlogLocationLambdaRole.Arn
      Code:
        ZipFile: !Sub |
          import boto3
          from botocore.exceptions import ClientError
          import json
          import os
          from boto3.dynamodb.conditions import Key, Attr
          import math


          # Use folloiwng Map Index. If Map Index Does not exist, it will be created.
          indexName = os.environ['TargetIndexName']
          ddb_table = os.environ['PoiTableName']
          route_calculator_name=os.environ['RouteCalculatorName']

          client = boto3.client("location")

          dynamodbClient = boto3.client('dynamodb')

          def lambda_handler(event, context):

              response=[]

              poiItem1=''
              poiItem2=''
              poiItem3=''
              pointOfInterest=''
              poiItemList=[]

              headers = {"Access-Control-Allow-Headers" : "Content-Type",
                          "Access-Control-Allow-Origin" : "*",
                          "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
              }


              try:

                  print (event)

                  #body=event['body']
                  body=json.loads(event['body'])
                  print (event['body'])

                  inputAddress=body['address']

                  pointOfInterest=body['poi']

                  print('address provided' + str(inputAddress))
                  print('point of interest' + str(pointOfInterest))

                  if len(inputAddress) == 0:
                      return {
                          'statusCode' : 200,
                          "headers": headers,
                          'body': json.dumps(
                          {
                              "PoiType": pointOfInterest,
                              "PointOfList" : poiItemList,
                              "error" : 'No Address is provided'
                          })
                      }

                  if len(pointOfInterest) == 0:
                      return {
                          'statusCode' : 200,
                          "headers": headers,
                          'body': json.dumps(
                          {
                              "PoiType": pointOfInterest,
                              "PoiList" : poiItemList,
                              "error" : 'No Point of Interest is provided'
                          })
                      }


                  print ("IndexName : " + str(indexName))


                  try:
                      response = client.describe_place_index(IndexName=indexName)
                  except client.exceptions.ResourceNotFoundException:
                      print ("Index name is not found")
                      return {
                          'statusCode' : 200,
                          'headers': headers,
                          'body': json.dumps(
                          {
                              "PoiType": pointOfInterest,
                              "PoiList" : poiItemList,
                              "error" : 'Index name is not found'
                          })
                      }



                  response=client.search_place_index_for_text(IndexName=indexName, Text=inputAddress)

                  print ("Results Count" , len(response['Results']))


                  if len(response['Results']) == 0:
                      return {
                          'statusCode' : 200,
                          'headers': headers,
                          'body': json.dumps(
                          {
                              "PoiType": pointOfInterest,
                              "PoiList" : poiItemList,
                              "error" : 'Invalid Address'
                          })
                      }


                  x = response['Results'][0]['Place']['Geometry']['Point'][0]
                  y = response['Results'][0]['Place']['Geometry']['Point'][1]

                  print ('address cooridinate - x,y' + str(x) + ',' + str(y) )


                  biasPositionCord=create_polygon(x, y, 2, 4)
                  print (biasPositionCord)
                  print (biasPositionCord[2][0])
                  print (biasPositionCord[2][1])

                  bboxCord= []

                  bboxCord= [ biasPositionCord[2][0],biasPositionCord[2][1], biasPositionCord[0][0], biasPositionCord[0][1] ]
                  print (bboxCord)

                  response=client.search_place_index_for_text(FilterBBox=bboxCord, IndexName=indexName, MaxResults=10, Text=pointOfInterest)
                  print ("Results Count" , len(response['Results']))

                  i=0

                  itemCount=len(response['Results'])

                  while i < itemCount:

                      print ("Label long/lat", response['Results'][i]['Place']['Geometry'])

                      item_details = get_poi_details(str(i))

                      distanceResponse = client.calculate_route(CalculatorName=route_calculator_name, DeparturePosition=[x,y], DestinationPosition= response['Results'][i]['Place']['Geometry']['Point'])

                      distance = distanceResponse['Summary']['Distance']

                      print ('distance=', distance)

                      singleItem = {
                          "Label" : response['Results'][i]['Place']['Label'],
                          "LongLat" : response['Results'][i]['Place']['Geometry']['Point'],
                          "DistanceInKm" : distance,
                          "Hours" : item_details['Hours_Of_Operation'],
                          "Telephone" : item_details['Telephone']
                      }


                      poiItemList.insert(i, singleItem)
                      print ('item', i, response['Results'][i]['Place']['Label'] )
                      i+=1

                  print ('list', poiItemList)

                  return {
                      'statusCode' : 200,
                      "headers": headers,
                      'body': json.dumps(
                          {
                              'longitude': x,
                              'latitude' : y,
                              "PoiType": pointOfInterest,
                              "PoilList" : poiItemList,
                              "error" : ''
                          }
                      )
                  }



              except Exception as e:
                  print ('Exception Error: ' + str(e))
                  return {
                      'statusCode' : 200,
                      'headers': headers,
                      'body': json.dumps(
                          {
                              "error" : str(e)
                          }
                      )
                  }


          def get_poi_details(poi_label):

              response =dynamodbClient.get_item(
                  TableName=ddb_table,
                  Key={
                      'poi_label': {
                          'S':poi_label
                      }
                  }
              )

              print ("After Call", response['Item'])
              if response:
                  return {

                      'Label': poi_label,
                      'Telephone': response['Item']['telephone_number']['S'],
                      'Hours_Of_Operation': response['Item']['hours_of_operation']['S']
                  }
              else:
                  return {}

          #creates polygon
          def create_polygon(longitude, latitude, radius=0.0008, vertices=6):
              center = (longitude,latitude)

              angle = 0
              angle -= (math.pi/vertices)

              coord_list = [[center[0] + radius * math.sin((2*math.pi/vertices) * i - angle), center[1] + radius * math.cos((2*math.pi/vertices) * i - angle)] for i in range(vertices)]
              coord_list.append(coord_list[0])

              return coord_list


  BlogDDBLambdaRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - !Ref BlogDDBLambdaPolicy

  BlogDDBLambdaPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: !Sub ${AWS::StackName}-blog-ddb-lambda-policy
      Path: /
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - dynamodb:PutItem
            Resource: "*"


  BlogLocationLambdaRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - !Ref BlogLocationLambdaPolicy

  BlogLocationLambdaPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: !Sub ${AWS::StackName}-blog-location-ddb-policy
      Path: /
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - dynamodb:GetItem
              - geo:CreatePlaceIndex
              - geo:DescribePlaceIndex
              - geo:SearchPlaceIndexForText
              - geo:SearchPlaceIndexForPosition
              - geo:CalculateRoute
              - logs:CreateLogGroup
              - logs:CreateLogStream
              - logs:PutLogEvents
            Resource: "*"

  GetPoiDetailsApi:
    Properties:
      Description: Get Point of Details API
      EndpointConfiguration:
        Types:
        - EDGE
      FailOnWarnings: true
      Name: GetPoiDetailsApi
      Policy:
        Statement:
        - Action: execute-api:Invoke
          Effect: Allow
          Principal: '*'
          Resource: '*'
        Version: '2012-10-17'
    Type: AWS::ApiGateway::RestApi

  GetPoiDetailsApiResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      ParentId: !GetAtt
        - GetPoiDetailsApi
        - RootResourceId
      PathPart: 'GetPoiDetailsApi-GetPoiDetails'
      RestApiId: !Ref GetPoiDetailsApi

  GetPoiApiDetailsRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Action:
          - sts:AssumeRole
          Effect: Allow
          Principal:
            Service:
            - apigateway.amazonaws.com
        Version: '2012-10-17'
      Path: '/'
      ManagedPolicyArns:
        - !Ref GetPoiApiLambdaAccessPolicy

  GetPoiApiLambdaAccessPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: !Sub ${AWS::StackName}-get-poi-api-lambda-access
      Path: /
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Action:
          - lambda:InvokeFunction
          Effect: Allow
          Resource:
            - !GetAtt GetPoiDetails.Arn

  GetPoiDetailsApiDeployment:
    DependsOn:
      - GetPoiDetailsApiMethod
    Properties:
      RestApiId: !Ref GetPoiDetailsApi
    Type: AWS::ApiGateway::Deployment


  GetPoiDetailsApiMethod:
    Type: AWS::ApiGateway::Method
    DependsOn: GetPoiDetailsApi
    Properties:
      ResourceId: !Ref GetPoiDetailsApiResource
      RestApiId: !Ref GetPoiDetailsApi
      AuthorizationType: NONE
      HttpMethod: POST
      Integration:
        IntegrationHttpMethod: POST
        Credentials: !GetAtt GetPoiApiDetailsRole.Arn
        Type: AWS_PROXY
        Uri:
          Fn::Join:
          - ''
          - - 'arn:aws:apigateway:'
            - Ref: AWS::Region
            - :lambda:path/2015-03-31/functions/
            - Fn::GetAtt:
              - GetPoiDetails
              - Arn
            - /invocations
        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: "'POST,OPTIONS'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
            ResponseTemplates:
              application/json: ''
        PassthroughBehavior: WHEN_NO_MATCH
        RequestTemplates:
          application/json: '{"statusCode": 200}'
      MethodResponses:
        - 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
          StatusCode: 200

  GetPoiDetailsApiMethodOPTIONS:
    Type: AWS::ApiGateway::Method
    DependsOn: GetPoiDetailsApi
    Properties:
      ResourceId: !Ref GetPoiDetailsApiResource
      RestApiId: !Ref GetPoiDetailsApi
      AuthorizationType: NONE
      HttpMethod: OPTIONS
      Integration:
        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: "'POST,OPTIONS'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
            ResponseTemplates:
              application/json: ''
        PassthroughBehavior: WHEN_NO_MATCH
        RequestTemplates:
          application/json: '{"statusCode": 200}'
        Type: MOCK
      MethodResponses:
        - ResponseModels:
            application/json: 'Empty'
          ResponseParameters:
            method.response.header.Access-Control-Allow-Headers: false
            method.response.header.Access-Control-Allow-Methods: false
            method.response.header.Access-Control-Allow-Origin: false
          StatusCode: 200


  GetPoiDetailsApiModel:
    Type: AWS::ApiGateway::Model
    Properties:
      ContentType: 'application/json'
      RestApiId: !Ref GetPoiDetailsApi
      Schema: {}

  GetPoiDetailsApiStage:
    DependsOn: GetPoiDetailsApi
    Properties:
      DeploymentId: !Ref GetPoiDetailsApiDeployment
      MethodSettings:
      - DataTraceEnabled: true
        HttpMethod: '*'
        LoggingLevel: INFO
        ResourcePath: /*
      RestApiId: !Ref GetPoiDetailsApi
      StageName: Prod
    Type: AWS::ApiGateway::Stage


  LambdaApiGatewayInvokeForGetPoiDetails:
    Type: "AWS::Lambda::Permission"
    DependsOn: GetPoiDetailsApiMethod
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt "GetPoiDetails.Arn"
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${GetPoiDetailsApi}/*/POST/GetPoiDetailsApi-GetPoiDetails"
