// <copyright file="FinancialCardTrackOne.cs" company="Scriptel Corporation">
//      Copyright 2014 - Scriptel Corporation
// </copyright>
namespace EasyScriptAPI
{
    using System;
    using System.Text;
    using System.Text.RegularExpressions;

    /// <summary>
    /// This class represents track one of a financial card.
    /// </summary>
    public class FinancialCardTrackOne
    {
        /// <summary>
        /// The credit card number of this financial card.
        /// </summary>
        private string accountNumber;

        /// <summary>
        /// The first name on the card.
        /// </summary>
        private string firstName;

        /// <summary>
        ///  The last name on the card.
        /// </summary>
        private string lastName;

        /// <summary>
        /// The expiration date on the card.
        /// </summary>
        private DateTime expiration;

        /// <summary>
        /// The service code on the card.
        /// </summary>
        private string serviceCode;

        /// <summary>
        /// Optional additional data the issuer has included on the strip.
        /// </summary>
        private string discretionaryData;
    
        /// <summary>
        /// This method attempts to parse track one out the raw track string.
        /// </summary>
        /// <param name="trackData">Track data to parse</param>
        /// <returns>FinancialCardTrackOne data if data found, null otherwise.></returns>
        public static FinancialCardTrackOne Parse(string trackData)
        {
            Regex regex = new Regex(".*%[A-Z]{1}(\\d{1,19})\\^([^\\^]{1,30})\\^(\\d{2})(\\d{2})([0-9]{3})([A-Za-z 0-9]*)\\?.*");
            Match m = regex.Match(trackData);
            if (m.Success)
            {
                FinancialCardTrackOne track = new FinancialCardTrackOne();
                track.SetAccountNumber(m.Groups[1].Value);
                track.SetServiceCode(m.Groups[5].Value);
                track.SetDiscretionaryData(m.Groups[6].Value);
            
                string name = m.Groups[2].Value;
                int idx = name.IndexOf('/');
                if (idx >= 0)
                {
                    track.SetLastName(name.Substring(0, idx).Trim());
                    track.SetFirstName(name.Substring(idx + 1).Trim());
                }
                else
                {
                    track.SetFirstName(name.Trim());
                    track.SetLastName(string.Empty);
                }
            
                int year = int.Parse(m.Groups[3].Value) + 2000;
                int month = int.Parse(m.Groups[4].Value);

                DateTime thisMonth = new DateTime(year, month, 1, 0, 0, 0, 0);
                DateTime nextMonth = thisMonth.AddMonths(1);
                track.SetExpiration(nextMonth.AddMilliseconds(-1));
            
                return track;
            }

            return null;
        }

        /// <summary>
        /// Returns this object as a human readable string.
        /// </summary>
        /// <returns>String containing human readable string</returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            string ln = Environment.NewLine;
            sb.Append("Financial Card - Track One:").Append(ln);
            sb.Append("    Account Number: ").Append(this.accountNumber).Append(ln);
            sb.Append("        First Name: ").Append(this.firstName).Append(ln);
            sb.Append("         Last Name: ").Append(this.lastName).Append(ln);
            sb.Append("        Expiration: ").Append(this.expiration).Append(ln);
            sb.Append("      Service Code: ").Append(this.serviceCode).Append(ln);
            sb.Append("Discretionary Data: ").Append(this.discretionaryData).Append(ln);
            return sb.ToString();
        }
    
        /// <summary>
        /// Gets the account number on the card
        /// </summary>
        /// <returns>the account number</returns>
        public string GetAccountNumber()
        {
            return this.accountNumber;
        }

        /// <summary>
        /// Gets the first name on the card
        /// </summary>
        /// <returns>The first name on the card</returns>
        public string GetFirstName()
        {
            return this.firstName;
        }
        
        /// <summary>
        /// Gets the last name on the card
        /// </summary>
        /// <returns>the last name on the card</returns>
        public string GetLastName()
        {
            return this.lastName;
        }
        
        /// <summary>
        /// Gets the expiration date of the card
        /// </summary>
        /// <returns>The expiration date of the card</returns>
        public DateTime GetExpiration()
        {
            return this.expiration;
        }
       
        /// <summary>
        /// Gets the service code on the card
        /// </summary>
        /// <returns>The service code on the card</returns>
        public string GetServiceCode()
        {
            return this.serviceCode;
        }
       
        /// <summary>
        /// Gets the vendor-specific discretionary data on the card.
        /// </summary>
        /// <returns>The vendor-specific discretionary data on the card.</returns>
        public string GetDiscretionaryData()
        {
            return this.discretionaryData;
        }

        /// <summary>
        /// Sets the account number on the card
        /// </summary>
        /// <param name="accountNumber">the account number</param>
        private void SetAccountNumber(string accountNumber)
        {
            this.accountNumber = accountNumber;
        }

        /// <summary>
        /// Sets the first name on the card
        /// </summary>
        /// <param name="firstName">the first name on the card</param>
        private void SetFirstName(string firstName)
        {
            this.firstName = firstName;
        }

        /// <summary>
        /// Sets the last name on the card
        /// </summary>
        /// <param name="lastName">the last name on the card</param>
        private void SetLastName(string lastName)
        {
            this.lastName = lastName;
        }

        /// <summary>
        /// Sets the expiration date of the card
        /// </summary>
        /// <param name="expiration">The expiration date of the card</param>
        private void SetExpiration(DateTime expiration)
        {
            this.expiration = expiration;
        }

        /// <summary>
        /// Sets the service code on the card
        /// </summary>
        /// <param name="serviceCode">The service code on the card</param>
        private void SetServiceCode(string serviceCode)
        {
            this.serviceCode = serviceCode;
        }

        /// <summary>
        /// Sets the vendor-specific discretionary data on the card.
        /// </summary>
        /// <param name="discretionaryData">The vendor-specific discretionary data on the card.</param>
        private void SetDiscretionaryData(string discretionaryData)
        {
            this.discretionaryData = discretionaryData;
        }
    }
}
