/*
         * Update a province from the file.
         *  - pv : Province class object
         */
        public void HKUpdate(HKProvince pv)
        {
            try
            {
                // Call HKEdit method to check can edit
                HKEdit(pv);

                if (IsEdit)
                {
                    HKDelete(pv.ProvinceCode);
                    using (SW = new StreamWriter(FILENAME, append: true))
                    {
                        SW.WriteLine(pv.ToString());
                    }

                    SW.Close();
                }

                else
                {
                    throw new Exception(string.Format("province code [{0}] " +
                                                      "already on file.", pv.ProvinceCode));
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        /*
         * Called in another method. Parsing the stringl to make each field.
         *  - sRecord made with the delimiter(-) like this
         *      "ProvinceCode-ProvinceName-CountryCode..."
         *  - return : Province class object
         */
        public HKProvince HKParseProvince(string sRecord)
        {
            string[]   sArry = sRecord.Split('-');
            HKProvince pv    = new HKProvince();

            if (sArry.Length != 6)
            {
                throw new Exception("Its not a province record.");
            }
            else
            {
                pv.ProvinceCode       = sArry[0];
                pv.Name               = sArry[1];
                pv.CountryCode        = sArry[2];
                pv.TaxCode            = sArry[3];
                pv.TaxRate            = Convert.ToDouble(sArry[4]);
                pv.IncludesFederalTax = Convert.ToBoolean(sArry[5]);
            }

            return(pv);
        }
        /*
         * Get all provinces from the file. Called from HKAdd or HKUpdate.
         *  - pv : Province class object
         *  - return : Province list
         */
        private void HKEdit(HKProvince pv)
        {
            string sError      = "";
            Regex  codePattern = new Regex(@"^[a-zA-Z]{2}$");

            if (Utility.NullToString(pv.ProvinceCode) == "")
            {
                sError += "ProvinceCode is required.\n";
            }
            else if (!codePattern.IsMatch(ProvinceCode))
            {
                sError += "Province Code must be 2 letters.\n";
            }

            if (Utility.NullToString(pv.Name) == "")
            {
                sError += "Name is required.\n";
            }

            if (Utility.NullToString(pv.CountryCode) == "")
            {
                sError += "Country Code is required.\n";
            }
            else if (!codePattern.IsMatch(CountryCode))
            {
                sError += "Country Code must be 2 letters.\n";
            }

            IsEdit = (HKGetByProvinceCode(pv.ProvinceCode) == null) ? false : true;
            HKProvince checkPV = HKGetByProvinceName(pv.Name);

            //checkPV != null : already exist the same province code in the record
            // !IsEdit : Current state is can add
            // If the provinceCode retrieved is not the same as the provinceCode entered
            if (checkPV != null)
            {
                if (!IsEdit || checkPV.ProvinceCode != pv.ProvinceCode)
                {
                    throw new Exception(string.Format("Name [{0}] is " +
                                                      "already on file.\n", pv.Name));
                }
            }

            // TaxCode is provided. It can be empty/null
            //  - upper case
            //  - only letters.
            if (Utility.NullToString(pv.TaxCode) != "")
            {
                Regex taxPattern = new Regex(@"^[A-Z]+$");
                if (!taxPattern.IsMatch(pv.TaxCode.ToUpper()))
                {
                    sError += "Tax code must be only in letters.\n";
                }

                // TaxCode is not provided,
                //  - TaxRate must be zero.  Otherwise, it can be zero to one, inclusive.
                //  - Tax rate is between 0 and 1
                //      regardless of whether Taxcode is provided or not
                if (0 > pv.TaxRate || pv.TaxRate > 1)
                {
                    sError += "Tax rate must be 0, otherwise, " +
                              "it can be 0 to 1 inclusively.\n";
                }
            }
            else
            {
                if (0 < pv.TaxRate)
                {
                    sError += "Tax rate must be zero if TaxCode is empty/null.\n";
                }
            }


            //  - IncludesFederalTax must be false when TaxRate is zero.
            if (pv.TaxRate == 0 && pv.IncludesFederalTax)
            {
                sError += "Federal Tax cannot be included when tax rate is zero.\n";
            }

            if (sError == "")
            {
                ProvinceCode       = pv.ProvinceCode.ToUpper();
                Name               = Utility.HKoCapitalize(pv.Name);
                CountryCode        = pv.CountryCode.ToUpper();
                TaxCode            = pv.TaxCode.ToUpper();
                TaxRate            = pv.TaxRate;
                IncludesFederalTax = pv.IncludesFederalTax;
            }
            else
            {
                throw new Exception(sError);
            }
        }