using System;

namespace Valg.EVA.Skanning.ServicesModel.Internal.BallotNumber
{
    public static class BallotNumberGenerator
    {
        public static bool IsBallotNumberCheckSumValid(string number)
        {
            var numberWithoutCheckSum = number.Substring(0, number.Length - 2);
            var intCheckDigit = GenerateChecksumDigits(numberWithoutCheckSum);
            return number == numberWithoutCheckSum + String.Format("{0:00}", intCheckDigit);
        }

        public static int GenerateChecksumDigits(string numberWithoutCheckSum)
        {
            var intCheckDigit = 0;
            var intMultiplier = 2;
            for (var digitNo = numberWithoutCheckSum.Length; digitNo >= 1; digitNo--)
            {
                if (intMultiplier > 7)
                    intMultiplier = 2;

                var keyAscii = Convert.ToChar(numberWithoutCheckSum.Substring(digitNo - 1, 1));
                intCheckDigit = intCheckDigit + (Convert.ToInt32(keyAscii - 48)*intMultiplier);
                intMultiplier = intMultiplier + 1;
            }

            intCheckDigit = intCheckDigit%100;
            return intCheckDigit;
        }

        public static string GenerateBallotNumber(string electionEventId, string electionGroupId, string electionId, string contestId, string affiliationShortCode)
        {
            VerifyBallotNoPartIntegrity(electionEventId, BallotNumberSplitter.LengthOfElectionEventId);
            VerifyBallotNoPartIntegrity(electionGroupId, BallotNumberSplitter.LengthOfElectionGroupId);
            VerifyBallotNoPartIntegrity(electionId, BallotNumberSplitter.LengthOfElectionId);
            VerifyBallotNoPartIntegrity(contestId, BallotNumberSplitter.LengthOfContestId);
            VerifyBallotNoPartIntegrity(affiliationShortCode, BallotNumberSplitter.LengthOfAffiliationShortCode);

            var ballotNumberWithoutChecksum = string.Format("{0}{1}{2}{3}{4}", electionEventId, electionGroupId, electionId, contestId, affiliationShortCode);
            var withChecksum = ballotNumberWithoutChecksum + string.Format("{0:00}", GenerateChecksumDigits(ballotNumberWithoutChecksum));

            if (!IsBallotNumberCheckSumValid(withChecksum))
            {
                throw new ArgumentException("The system generated an invalid ballotNumber");
            }

            return withChecksum;
        }

        private static void VerifyBallotNoPartIntegrity(string ballotNoPart, int lengthOfPart)
        {
            if (!string.IsNullOrWhiteSpace(ballotNoPart) && ballotNoPart.Length == lengthOfPart)
            {
                decimal result;
                var success = decimal.TryParse(ballotNoPart, out result);
                if (!success)
                {
                    throw new ArgumentException("Part of ballotNo was not valid");                    
                }
            }
            else
            {
                throw new ArgumentException("Part of ballotNo was not valid");
            }
        }
    }
}
