// <copyright file="IdentificationCardTrackThree.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 three of a magnetic strip identification card
    /// such as a United States driver's license.
    /// </summary>
    public class IdentificationCardTrackThree
    {
        /// <summary>
        /// CDS protocol version number
        /// </summary>
        private string cdsVersion;

        /// <summary>
        /// jurisdiction version number
        /// </summary>
        private string jurisdictionVersion;

        /// <summary>
        /// postal code of the card holder
        /// </summary>
        private string postalCode;

        /// <summary>
        /// license class
        /// </summary>
        private string licenseClass;

        /// <summary>
        /// license restrictions
        /// </summary>
        private string restrictions;

        /// <summary>
        /// license endorsements
        /// </summary>
        private string endorsements;

        /// <summary>
        /// card holder gender
        /// </summary>
        private IdentificationSex sex;

        /// <summary>
        /// card holder height
        /// </summary>
        private string height;

        /// <summary>
        /// card holder weight
        /// </summary>
        private string weight;
        
        /// <summary>
        /// card holder hair color
        /// </summary>
        private string hairColor;

        /// <summary>
        /// card holder eye color
        /// </summary>
        private string eyeColor;

        /// <summary>
        /// vendor specific discretionary data
        /// </summary>
        private string discretionaryData;

        /// <summary>
        /// This method attempts to parse track three data out of the raw strip data
        /// </summary>
        /// <param name="trackData">track data to parse</param>
        /// <returns>IdentificationCardTrackThree data if possible, null otherwise.</returns>
        public static IdentificationCardTrackThree Parse(string trackData)
        {
            Regex regex = new Regex(".*%([0-9]{1})([0-9]{1})([A-Z 0-9]{11})([A-Z 0-9]{2})([A-Z 0-9]{10})([A-Z 0-9]{4})(1|2|M|F)([0-9 ]{3})([0-9 ]{3})([A-Z ]{3})([A-Z ]{3})([^\\?]{0,37})\\?.*");
            Match m = regex.Match(trackData);
            if (m.Success)
            {
                IdentificationCardTrackThree track = new IdentificationCardTrackThree();
                track.SetCdsVersion(m.Groups[1].Value);
                track.SetJurisdictionVersion(m.Groups[2].Value);
                track.SetPostalCode(m.Groups[3].Value);
                track.SetLicenseClass(m.Groups[4].Value.Trim());
                track.SetRestrictions(m.Groups[5].Value.Trim());
                track.SetEndorsements(m.Groups[6].Value.Trim());
                track.SetHeight(m.Groups[8].Value.Trim());
                track.SetWeight(m.Groups[9].Value.Trim());
                track.SetHairColor(m.Groups[10].Value.Trim());
                track.SetEyeColor(m.Groups[11].Value.Trim());
                track.SetDiscretionaryData(m.Groups[12].Value.Trim());

                char s = m.Groups[7].Value[0];
                IdentificationSex sex = (s == '1' || s == 'M') ? IdentificationSex.MALE : IdentificationSex.FEMALE;
                track.SetSex(sex);
            
                return track;
            }
        
            return null;
        }
    
        /// <summary>
        /// Returns this object as a human readable string
        /// </summary>
        /// <returns>this object as a human readable string</returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            string ln = Environment.NewLine;
            sb.Append("Identification Card - Track Three:").Append(ln);
            sb.Append("         CDS Version: ").Append(this.cdsVersion).Append(ln);
            sb.Append("Jurisdiction Version: ").Append(this.jurisdictionVersion).Append(ln);
            sb.Append("         Postal Code: ").Append(this.postalCode).Append(ln);
            sb.Append("       License Class: ").Append(this.licenseClass).Append(ln);
            sb.Append("        Restrictions: ").Append(this.restrictions).Append(ln);
            sb.Append("        Endorsements: ").Append(this.endorsements).Append(ln);
            sb.Append("                 Sex: ").Append(this.sex).Append(ln);
            sb.Append("              Height: ").Append(this.height).Append(ln);
            sb.Append("              Weight: ").Append(this.weight).Append(ln);
            sb.Append("          Hair Color: ").Append(this.hairColor).Append(ln);
            sb.Append("           Eye Color: ").Append(this.eyeColor).Append(ln);
            sb.Append("  Discretionary Data: ").Append(this.discretionaryData).Append(ln);
            return sb.ToString();
        }
    
        /// <summary>
        /// Gets the CDS protocol version number
        /// </summary>
        /// <returns>CDS protocol version number</returns>
        public string GetCdsVersion()
        {
            return this.cdsVersion;
        }

        /// <summary>
        /// Gets the jurisdiction version from the card.
        /// </summary>
        /// <returns>jurisdiction version from the card.</returns>
        public string GetJurisdictionVersion()
        {
            return this.jurisdictionVersion;
        }

        /// <summary>
        /// Gets the postal code from the card
        /// </summary>
        /// <returns>postal code from the card</returns>
        public string GetPostalCode()
        {
            return this.postalCode;
        }

        /// <summary>
        /// Gets the license class
        /// </summary>
        /// <returns>license class</returns>
        public string GetLicenseClass()
        {
            return this.licenseClass;
        }

        /// <summary>
        /// Gets the license restrictions
        /// </summary>
        /// <returns>license restrictions</returns>
        public string GetRestrictions()
        {
            return this.restrictions;
        }

        /// <summary>
        /// Gets license endorsements
        /// </summary>
        /// <returns>license endorsements</returns>
        public string GetEndorsements()
        {
            return this.endorsements;
        }

        /// <summary>
        /// Gets card holder gender
        /// </summary>
        /// <returns>card holder gender</returns>
        public IdentificationSex GetSex()
        {
            return this.sex;
        }

        /// <summary>
        /// Gets the card holder height
        /// </summary>
        /// <returns>card holder height</returns>
        public string GetHeight()
        {
            return this.height;
        }

        /// <summary>
        /// Gets the card holder weight
        /// </summary>
        /// <returns>card holder weight</returns>
        public string GetWeight()
        {
            return this.weight;
        }

        /// <summary>
        /// Gets the card holder hair color
        /// </summary>
        /// <returns>card holder hair color</returns>
        public string GetHairColor()
        {
            return this.hairColor;
        }

        /// <summary>
        /// Gets the card holder eye color
        /// </summary>
        /// <returns>card holder eye color</returns>
        public string GetEyeColor()
        {
            return this.eyeColor;
        }

        /// <summary>
        /// Gets the vendor specific discretionary data
        /// </summary>
        /// <returns>vendor specific discretionary data</returns>
        public string GetDiscretionaryData()
        {
            return this.discretionaryData;
        }

        /// <summary>
        /// Sets the CDS protocol version number
        /// </summary>
        /// <param name="cdsVersion">CDS protocol version number</param>
        private void SetCdsVersion(string cdsVersion)
        {
            this.cdsVersion = cdsVersion;
        }

        /// <summary>
        /// Sets the jurisdiction version on the card
        /// </summary>
        /// <param name="jurisdictionVersion">jurisdiction version on the card</param>
        private void SetJurisdictionVersion(string jurisdictionVersion)
        {
            this.jurisdictionVersion = jurisdictionVersion;
        }

        /// <summary>
        /// Sets the postal code on the card
        /// </summary>
        /// <param name="postalCode">postal code on the card</param>
        private void SetPostalCode(string postalCode)
        {
            this.postalCode = postalCode;
        }

        /// <summary>
        /// Sets the license class.
        /// </summary>
        /// <param name="licenseClass">license class.</param>
        private void SetLicenseClass(string licenseClass)
        {
            this.licenseClass = licenseClass;
        }

        /// <summary>
        /// Sets the license restrictions
        /// </summary>
        /// <param name="restrictions">license restrictions</param>
        private void SetRestrictions(string restrictions)
        {
            this.restrictions = restrictions;
        }

        /// <summary>
        /// Sets license endorsements
        /// </summary>
        /// <param name="endorsements">license endorsements</param>
        private void SetEndorsements(string endorsements)
        {
            this.endorsements = endorsements;
        }

        /// <summary>
        /// Sets the card holder gender
        /// </summary>
        /// <param name="sex">card holder gender</param>
        private void SetSex(IdentificationSex sex)
        {
            this.sex = sex;
        }

        /// <summary>
        /// Sets the card holder height
        /// </summary>
        /// <param name="height">card holder height</param>
        private void SetHeight(string height)
        {
            this.height = height;
        }

        /// <summary>
        /// Sets the card holder weight
        /// </summary>
        /// <param name="weight">card holder weight</param>
        private void SetWeight(string weight)
        {
            this.weight = weight;
        }

        /// <summary>
        /// Sets the card holder hair color
        /// </summary>
        /// <param name="hairColor">card holder hair color</param>
        private void SetHairColor(string hairColor)
        {
            this.hairColor = hairColor;
        }

        /// <summary>
        /// Sets the card holder eye color
        /// </summary>
        /// <param name="eyeColor">card holder eye color</param>
        private void SetEyeColor(string eyeColor)
        {
            this.eyeColor = eyeColor;
        }

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