using Amazon.Lambda.Core;
using Amazon.Lambda.LexEvents;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Text;
using static BlueprintBaseName._1.FlowerOrder;
namespace BlueprintBaseName._1
{
public class OrderFlowersIntentProcessor : AbstractIntentProcessor
{
public const string TYPE_SLOT = "FlowerType";
public const string PICK_UP_DATE_SLOT = "PickupDate";
public const string PICK_UP_TIME_SLOT = "PickupTime";
public const string INVOCATION_SOURCE = "invocationSource";
FlowerTypes _chosenFlowerType = FlowerTypes.Null;
///
/// Performs dialog management and fulfillment for ordering flowers.
///
/// Beyond fulfillment, the implementation for this intent demonstrates the following:
/// 1) Use of elicitSlot in slot validation and re-prompting
/// 2) Use of sessionAttributes to pass information that can be used to guide the conversation
///
///
///
///
public override LexResponse Process(LexEvent lexEvent, ILambdaContext context)
{
IDictionary slots = lexEvent.CurrentIntent.Slots;
IDictionary sessionAttributes = lexEvent.SessionAttributes ?? new Dictionary();
//if all the values in the slots are empty return the delegate, theres nothing to validate or do.
if (slots.All(x => x.Value == null))
{
return Delegate(sessionAttributes, slots);
}
//if the flower slot has a value, validate that it is contained within the enum list available.
if (slots[TYPE_SLOT] != null)
{
var validateFlowerType = ValidateFlowerType(slots[TYPE_SLOT]);
if (!validateFlowerType.IsValid)
{
slots[validateFlowerType.ViolationSlot] = null;
return ElicitSlot(sessionAttributes, lexEvent.CurrentIntent.Name, slots, validateFlowerType.ViolationSlot, validateFlowerType.Message);
}
}
//now that enum has been parsed and validated, create the order
FlowerOrder order = CreateOrder(slots);
if (string.Equals(lexEvent.InvocationSource, "DialogCodeHook", StringComparison.Ordinal))
{
//validate the remaining slots.
var validateResult = Validate(order);
// If any slots are invalid, re-elicit for their value
if (!validateResult.IsValid)
{
slots[validateResult.ViolationSlot] = null;
return ElicitSlot(sessionAttributes, lexEvent.CurrentIntent.Name, slots, validateResult.ViolationSlot, validateResult.Message);
}
// Pass the price of the flowers back through session attributes to be used in various prompts defined
// on the bot model.
if (order.FlowerType.Value != FlowerTypes.Null)
{
sessionAttributes["Price"] = (order.FlowerType.Value.ToString().Length * 5).ToString();
}
return Delegate(sessionAttributes, slots);
}
return Close(
sessionAttributes,
"Fulfilled",
new LexResponse.LexMessage
{
ContentType = MESSAGE_CONTENT_TYPE,
Content = String.Format("Thanks, your order for {0} has been placed and will be ready for pickup by {1} on {2}.", order.FlowerType.ToString(), order.PickUpTime, order.PickUpDate)
}
);
}
private FlowerOrder CreateOrder(IDictionary slots)
{
FlowerOrder order = new FlowerOrder
{
FlowerType = _chosenFlowerType,
PickUpDate = slots.ContainsKey(PICK_UP_DATE_SLOT) ? slots[PICK_UP_DATE_SLOT] : null,
PickUpTime = slots.ContainsKey(PICK_UP_TIME_SLOT) ? slots[PICK_UP_TIME_SLOT] : null
};
return order;
}
///
/// Verifies that any values for slots in the intent are valid.
///
///
///
private ValidationResult Validate(FlowerOrder order)
{
if (!string.IsNullOrEmpty(order.PickUpDate))
{
DateTime pickUpDate = DateTime.MinValue;
if (!DateTime.TryParse(order.PickUpDate, out pickUpDate))
{
return new ValidationResult(false, PICK_UP_DATE_SLOT,
"I did not understand that, what date would you like to pick the flowers up?");
}
if (pickUpDate < DateTime.Today)
{
return new ValidationResult(false, PICK_UP_DATE_SLOT,
"You can pick up the flowers from tomorrow onwards. What day would you like to pick them up?");
}
}
if (!string.IsNullOrEmpty(order.PickUpTime))
{
string[] timeComponents = order.PickUpTime.Split(":");
Double hour = Double.Parse(timeComponents[0]);
Double minutes = Double.Parse(timeComponents[1]);
if (Double.IsNaN(hour) || Double.IsNaN(minutes))
{
return new ValidationResult(false, PICK_UP_TIME_SLOT, null);
}
if (hour < 10 || hour >= 17)
{
return new ValidationResult(false, PICK_UP_TIME_SLOT, "Our business hours are from ten a m. to five p m. Can you specify a time during this range?");
}
}
return ValidationResult.VALID_RESULT;
}
///
/// Verifies that any values for flower type slot in the intent is valid.
///
///
///
private ValidationResult ValidateFlowerType(string flowerTypeString)
{
bool isFlowerTypeValid = Enum.IsDefined(typeof(FlowerTypes), flowerTypeString.ToUpper());
if (Enum.TryParse(typeof(FlowerTypes), flowerTypeString, true, out object flowerType))
{
_chosenFlowerType = (FlowerTypes)flowerType;
return ValidationResult.VALID_RESULT;
}
else
{
return new ValidationResult(false, TYPE_SLOT, String.Format("We do not have {0}, would you like a different type of flower? Our most popular flowers are roses", flowerTypeString));
}
}
}
}