import boto3
from boto3.dynamodb.conditions import Key, Attr
import os
from contextlib import closing
import json


def convert_to_video(event, context):
    postId = event["Records"][0]["Sns"]["Message"]

    # Retrieving information about the post from DynamoDB table
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table(os.environ['DYNAMODB_TABLE'])
    postItem = table.query(
        KeyConditionExpression=Key('id').eq(postId)
    )

    text = postItem["Items"][0]["text"]
    voice = postItem["Items"][0]["voice"]

    rest = text

    # Because single invocation of the polly synthesize_speech api can
    # transform text with about 1,500 characters, we are dividing the
    # post into blocks of approximately 1,000 characters.
    textBlocks = []
    while len(rest) > 1100:
        begin = 0
        end = rest.find(".", 1000)

        if end == -1:
            end = rest.find(" ", 1000)

        textBlock = rest[begin:end]
        rest = rest[end:]
        textBlocks.append(textBlock)
    textBlocks.append(rest)

    # For each block, invoke Polly API, which will transform text into audio
    polly = boto3.client('polly')
    for textBlock in textBlocks:
        response = polly.synthesize_speech(
            OutputFormat='mp3',
            Text=textBlock,
            VoiceId=voice
        )

        # Save the audio stream returned by Amazon Polly on Lambda's temp
        # directory. If there are multiple text blocks, the audio stream
        # will be combined into a single file.
        if "AudioStream" in response:
            with closing(response["AudioStream"]) as stream:
                output = os.path.join("/tmp/", postId)
                with open(output, "a") as file:
                    file.write(stream.read())

    s3 = boto3.client('s3')
    s3.upload_file('/tmp/' + postId,
                   os.environ['BUCKET_NAME'],
                   postId + ".mp3")
    s3.put_object_acl(ACL='public-read',
                      Bucket=os.environ['BUCKET_NAME'],
                      Key=postId + ".mp3")

    location = s3.get_bucket_location(Bucket=os.environ['BUCKET_NAME'])
    region = location['LocationConstraint']

    url = "https://s3%(region)s.amazonaws.com/%(bucket_name)s/%(postId)s.mp3" % {
        "region": "-%s" % str(region) if region else "",
        "bucket_name": os.environ['BUCKET_NAME'],
        "postId": str(postId)
    }

    # Updating the item in DynamoDB
    response = table.update_item(
        Key={'id': postId},
        UpdateExpression=
        "SET #statusAtt = :statusValue, #urlAtt = :urlValue",
        ExpressionAttributeValues=
        {':statusValue': 'UPDATED', ':urlValue': url},
        ExpressionAttributeNames=
        {'#statusAtt': 'status', '#urlAtt': 'url'},
    )

    response = {
        "statusCode": 200,
        "body": json.dumps(response)
    }
    return response
