using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Xml.Serialization;
using CareFusion.Mosaic.Converters.Wwks2.Types;
using CareFusion.Mosaic.Interfaces.Converters;
using CareFusion.Mosaic.Interfaces.Messages;
using CareFusion.Mosaic.Interfaces.Types.Packs;
using CareFusion.Mosaic.Interfaces.Types.Stock;
using Rowa.Mosaic.Shared.Converters;

namespace CareFusion.Mosaic.Converters.Wwks2.Messages.Input
{
    /// <summary>
    /// Class which represents the WWKS 2.0 InfeedInputRequest message envelope.
    /// </summary>
    [XmlType(TypeName = "WWKS")]
    [ExcludeFromCodeCoverage]
    public class InfeedInputRequestEnvelope : EnvelopeBase, IMessageConversion
    {
        [XmlElement]
        public InfeedInputRequest InfeedInputRequest { get; set; }

        /// <summary>
        /// Translates this object instance into a Mosaic message.
        /// </summary>
        /// <param name="converterStream">The converter stream instance which request the message conversion.</param>
        /// <returns>
        /// The Mosaic message representation of this object.
        /// </returns>
        public MosaicMessage ToMosaicMessage(IConverterStream converterStream)
        {
            return this.InfeedInputRequest.ToMosaicMessage(converterStream);
        }
    }

    /// <summary>
    /// Class which represents the WWKS 2.0 InfeedInputRequest message.
    /// <see cref="https://portalrowa.carefusion.com/Unternehmen/Entwicklung/TechCom/Writing/P-010-044-B-I-388-DEU.docx" />
    /// </summary>
    public class InfeedInputRequest : MessageBase, IMessageConversion
    {
        #region Properties

        [XmlAttribute]
        public string IsNewDelivery { get; set; }

        [XmlAttribute]
        public string SetPickingIndicator { get; set; }

        [XmlElement]
        public Details Details { get; set; }

        [XmlElement]
        public Article Article { get; set; }

        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="InfeedInputRequest"/> class.
        /// </summary>
        [ExcludeFromCodeCoverage]
        public InfeedInputRequest()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="InfeedInputRequest"/> class.
        /// </summary>
        /// <param name="message">The message to use for initialization.</param>
        public InfeedInputRequest(MosaicMessage message)
        {
            var request = (Interfaces.Messages.Input.InfeedInputRequest)message;

            this.Id = request.ID;
            this.Destination = request.Destination;
            this.Source = request.Source;
            this.IsNewDelivery = request.IsDeliveryInput.ToString();
            this.SetPickingIndicator = request.SetPickingIndicator.ToString();
            this.Details = new Details()
            {
                InfeedNumber = request.InfeedNumber.ToString()
            };

            this.Article = new Article();

            if (request.Packs.Count > 0)
            {
                this.Article.Pack = new List<Pack>();

                int packIndex = 0;

                foreach (var pack in request.Packs)
                {
                    this.Article.Pack.Add(new Pack()
                    {
                        Index = packIndex.ToString(),
                        ScanCode = TextConverter.EscapeInvalidXmlChars(pack.ScanCode),
                        DeliveryNumber = TextConverter.EscapeInvalidXmlChars(pack.DeliveryNumber),
                        BatchNumber = TextConverter.EscapeInvalidXmlChars(pack.BatchNumber),
                        ExternalId = TextConverter.EscapeInvalidXmlChars(pack.ExternalID),
                        SerialNumber = TextConverter.EscapeInvalidXmlChars(pack.SerialNumber),
                        ExpiryDate = TypeConverter.ConvertDateNull(pack.ExpiryDate),
                        ExpiryDateSource = pack.ExpiryDateSource.ToString() ?? ExpiryDateSource.Unknown.ToString(),
                        SubItemQuantity = pack.SubItemQuantity.ToString(),
                        Depth = pack.Depth.ToString(),
                        Width = pack.Width.ToString(),
                        Height = pack.Height.ToString(),
                        Shape = pack.Shape.ToString(),
                        StockLocationId = TextConverter.EscapeInvalidXmlChars(pack.StockLocationID),
                        MachineLocation = TextConverter.EscapeInvalidXmlChars(pack.MachineLocation),
                        GUID = pack.Guid
                    });

                    packIndex++;
                }
            }
        }

        /// <summary>
        /// Translates this object instance into a Mosaic message.
        /// </summary>
        /// <param name="converterStream">The converter stream instance which request the message conversion.</param>
        /// <returns>
        /// The Mosaic message representation of this object.
        /// </returns>
        public MosaicMessage ToMosaicMessage(IConverterStream converterStream)
        {
            var request = new Interfaces.Messages.Input.InfeedInputRequest(converterStream);

            request.ID = this.Id;
            request.Destination = this.Destination;
            request.Source = this.Source;
            request.IsDeliveryInput = TypeConverter.ConvertBool(this.IsNewDelivery);
            request.SetPickingIndicator = TypeConverter.ConvertBool(this.SetPickingIndicator);
            request.InfeedNumber = (this.Details != null) ? TypeConverter.ConvertInt(this.Details.InfeedNumber) : 0;

            if ((this.Article != null) && (this.Article.Pack != null))
            {
                foreach (var pack in this.Article.Pack)
                {
                    request.Packs.Add(new Interfaces.Types.Packs.RobotPack()
                    {
                        ScanCode = TextConverter.UnescapeInvalidXmlChars(pack.ScanCode),
                        DeliveryNumber = TextConverter.UnescapeInvalidXmlChars(pack.DeliveryNumber),
                        BatchNumber = TextConverter.UnescapeInvalidXmlChars(pack.BatchNumber),
                        ExternalID = TextConverter.UnescapeInvalidXmlChars(pack.ExternalId),
                        SerialNumber = TextConverter.UnescapeInvalidXmlChars(pack.SerialNumber),
                        ExpiryDate = TypeConverter.ConvertDate(pack.ExpiryDate),
                        ExpiryDateSource = TypeConverter.ConvertEnum<ExpiryDateSource>(pack.ExpiryDateSource, ExpiryDateSource.Unknown),
                        SubItemQuantity = TypeConverter.ConvertInt(pack.SubItemQuantity),
                        Depth = TypeConverter.ConvertInt(pack.Depth),
                        Width = TypeConverter.ConvertInt(pack.Width),
                        Height = TypeConverter.ConvertInt(pack.Height),
                        Shape = TypeConverter.ConvertEnum<PackShape>(pack.Shape, PackShape.Cuboid),
                        StockLocationID = string.IsNullOrEmpty(pack.StockLocationId) ? string.Empty : TextConverter.UnescapeInvalidXmlChars(pack.StockLocationId),
                        MachineLocation = string.IsNullOrEmpty(pack.MachineLocation) ? string.Empty : TextConverter.UnescapeInvalidXmlChars(pack.MachineLocation),
                        Guid = pack.GUID
                    });
                }
            }

            return request;
        }
    }
}
