using System.IO;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.PixelFormats;
using Amazon.S3.Model;
using SixLabors.ImageSharp.Formats.Jpeg;
using Amazon.Lambda.Core;
using Amazon.Lambda.S3Events;
using Amazon.S3;
using Amazon.S3.Util;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace ImageResize;
public class Function
{
    IAmazonS3 S3Client { get; set; }
    /// 
    /// Default constructor. This constructor is used by Lambda to construct the instance. When invoked in a Lambda environment
    /// the AWS credentials will come from the IAM role associated with the function and the AWS region will be set to the
    /// region the Lambda function is executed in.
    /// 
    public Function()
    {
        S3Client = new AmazonS3Client();
    }
    /// 
    /// Constructs an instance with a preconfigured S3 client. This can be used for testing outside of the Lambda environment.
    /// 
    /// 
    public Function(IAmazonS3 s3Client)
    {
        this.S3Client = s3Client;
    }
    public async Task FunctionHandler(S3Event evnt, ILambdaContext context)
    {
        string[] fileExtentions = new string[] { ".jpg", ".jpeg" };
        var s3Event = evnt.Records?[0].S3;
        if (s3Event == null)
        {
            return null;
        }
        try
        {
            foreach (var record in evnt.Records)
            {
                LambdaLogger.Log("----> File: " + record.S3.Object.Key);
                if (!fileExtentions.Contains(Path.GetExtension(record.S3.Object.Key).ToLower()))
                {
                    LambdaLogger.Log("File Extension is not supported - " + s3Event.Object.Key);
                    continue;
                }
                string suffix = Path.GetExtension(record.S3.Object.Key).ToLower();
                Stream imageStream = new MemoryStream();
                using (var objectResponse = await S3Client.GetObjectAsync(record.S3.Bucket.Name, record.S3.Object.Key))
                {
                    using (Stream responseStream = objectResponse.ResponseStream)
                    {
                        using (var image = Image.Load(responseStream))
                        {
                            // Create B&W thumbnail
                            image.Mutate(ctx => ctx.Grayscale().Resize(200, 200));
                            image.Save(imageStream, new JpegEncoder());
                            imageStream.Seek(0, SeekOrigin.Begin);
                        }
                    }
                }
                // Creating a new S3 ObjectKey for the thumbnails
                string thumbnailObjectKey = null;
                int endSlash = record.S3.Object.Key.ToLower().LastIndexOf("/");
                if (endSlash > 0)
                {
                    string S3ObjectName = record.S3.Object.Key.ToLower().Substring(endSlash + 1);
                    int beginSlash = 0;
                    if (endSlash > 0)
                    {
                        beginSlash = record.S3.Object.Key.ToLower().Substring(0, endSlash - 1).LastIndexOf("/");
                        if (beginSlash > 0)
                        {
                            thumbnailObjectKey =
                                record.S3.Object.Key.ToLower().Substring(0, beginSlash) +
                                "thumbnails/" +
                                S3ObjectName;
                        }
                        else
                        {
                            thumbnailObjectKey = "thumbnails/" + S3ObjectName;
                        }
                    }
                }
                else
                {
                    thumbnailObjectKey = "thumbnails/" + record.S3.Object.Key.ToLower();
                }
                LambdaLogger.Log("----> Thumbnail file Key: " + thumbnailObjectKey);
                await S3Client.PutObjectAsync(new PutObjectRequest
                {
                    BucketName = record.S3.Bucket.Name,
                    Key = thumbnailObjectKey,
                    InputStream = imageStream
                });
            }
            LambdaLogger.Log("Processed " + evnt.Records.Count.ToString());
            return null;
        }
        catch (Exception e)
        {
            context.Logger.LogLine($"Error getting object {s3Event.Object.Key} from bucket {s3Event.Bucket.Name}");
            context.Logger.LogLine($"Make sure they exist and your bucket is in the same region as this function");
            context.Logger.LogLine(e.Message);
            context.Logger.LogLine(e.StackTrace);
            throw;
        }
    }
}