/// <summary>
        /// Mapping from Specialist profile, country permitted, standard hour and user informatiom to SpecialistProfileViewModel
        /// </summary>
        /// <param name="specialization"></param>
        /// <param name="specProfile"></param>
        /// <param name="standardHour"></param>
        /// <returns></returns>
        public static SpecialistProfileViewModel ModelMapper(
            UserDto account, Guid? currentUserId, IServices Services)
        {
            SpecialistProfileViewModel model = new SpecialistProfileViewModel();
            model.Account = Mapper.Map<UserDto, UserViewModel>(account);

            SpecialistRegisterStep3ViewModel step3Model = new SpecialistRegisterStep3ViewModel();
            step3Model = Mapper.Map<ProfileDto, SpecialistRegisterStep3ViewModel>(account.Profile);

            step3Model.ListStandardHour = Mapper.Map<List<WorkingScheduleDto>, List<WorkingScheduleDto>>(account.Profile.WorkingSchedules.ToList());
            step3Model.Specializations = Mapper.Map<List<SpecializationDto>, List<SpecializationViewModel>>(account.Profile.Specializations.ToList());

            List<PermittedCountryViewModel> lstCountryPermitted = new List<PermittedCountryViewModel>();
            List<StateAndRegulatory> lstStateAndRegulatory = new List<StateAndRegulatory>();

            foreach (var spec in step3Model.Specializations)
            {
                foreach (var country in spec.PermittedCountries)
                {
                    var tempState = country.State.Split('_').ToList();
                    var tempRegulatory = country.RegulatoryAuthority.Split('_').ToList();
                    lstStateAndRegulatory = new List<StateAndRegulatory>();
                    for (int i = 0; i < tempState.Count(); i++)
                    {
                        if (!string.IsNullOrEmpty(tempState[i])
                            && !string.IsNullOrEmpty(tempRegulatory[i]))
                        {
                            lstStateAndRegulatory.Add(
                                new StateAndRegulatory
                                {
                                    State = tempState[i],
                                    Regulatory = tempRegulatory[i]
                                });
                        }
                    }
                    lstCountryPermitted.Add(new PermittedCountryViewModel { Name = country.Name, StatesAndRegulatories = lstStateAndRegulatory });
                }

                spec.lstCountryPermitted = lstCountryPermitted;

                spec.CustomerPricing = Services.Booking.GetCustomerPricing(spec.Id);

                // Format S3 link
                for (int i = 0; i < spec.POCs.Count; i++)
                {
                    spec.POCs[i].S3FileName = TeleConsult.Web.Code.Helpers.S3ReaderHelper.CombineFileS3Root(spec.POCs[i].S3FileName);
                }
            }

            if (string.IsNullOrEmpty(model.Account.AvatarPath))
            {
                model.Account.AvatarPath = ConstPath.DefaulAvatar;
            }
            else
            {
                var s3Root = BlueChilli.Web.Helpers.S3PathWithoutQuery("").Substring(1);
                model.Account.AvatarPath = Path.Combine(s3Root, account.Avatar);
            }

            model.SpecialistDetail = step3Model;

            model.IsFavourite = Services.Users.IsFavourite(model.Account.Id, currentUserId);

            model.SpecialistDetail.RatingRatio = (int)Math.Round(Services.Booking.RatingCalculator(account.Id), 0, MidpointRounding.AwayFromZero);

            //check current status is not "Not Available". if It is yes, it access db to check call
            if (!AvailabilityStatus.NotAvailable.Equals(model.Account.CurrentAvailabilityStatus)
                && Services.Call.CheckCallInProgressBySpecialistId(model.Account.Id))
            {
                model.Account.CurrentAvailabilityStatus = AvailabilityStatus.NotAvailable;
            }

            return model;
        }
        public ActionResult SpecialistRegisterStep2(SpecialistRegisterStep3ViewModel model, Guid id)
        {
            model.Languages = Request.Params["LanguageList"];
            RemoveErrorForNewState(model, true);
            ViewBag.MaximumSize = Services.SystemConfig
                .GetValueByKey(TeleConsult.Infrastructure.Core.Const.SystemConfig.FILE_UPLOAD_LIMITS);
            ViewBag.CultureList = CultureHelper.ListOfCountry();

            if (model.Specializations == null)
            {
                return View(model);
            }

            if (!ModelState.IsValid)
            {
                return View(model);
            }

            if (!CultureHelper.ValidateLanguage(model.Languages))
            {
                ModelState.AddModelError("Languages",
                    string.Format(TeleConsult.Web.Code.Constants.InputInvalidValue, "Languages"));
                return View(model);
            }

            foreach (SpecializationViewModel specialization in model.Specializations)
            {
                if (specialization.LicenceToOperate)
                {
                    if (specialization.lstCountryPermitted == null)
                    {
                        ViewBag.Index = specialization.ProfessionalOrTrade;
                        ViewBag.WarningMessage = UiHints.WarningMessageTemplates.RequiredField;
                        return View(model);
                    }

                    if (model.file != null && model.file.Any())
                    {
                        var listFile = model.file.Where(f => f != null).ToList();
                        if (listFile != null && listFile.Count > 0)
                        {
                            for (var i = 0; i < listFile.Count(); i++)
                            {
                                var image = listFile[i];

                                decimal sizeLimit = 0;
                                if (FileHelper.CompareFileMaximumSize(image.ContentLength, ref sizeLimit, Services))
                                {
                                    var fileName = System.IO.Path.GetFileName(image.FileName);
                                    Regex regexPOC = new Regex(RegularExpressions.POCExtension);

                                    if (regexPOC.Match(fileName).Success)
                                    {
                                        specialization.POCs.Add(new POCDto
                                        {
                                            OriginalFileName = image.FileName,
                                            S3FileName = FileHelper.UploadPostedFileToS3(Services, image, "POC"),
                                            Status = "Unverified"
                                        });
                                    }
                                    else
                                    {
                                        ModelState.AddModelError(
                                            "POCImage",
                                            string.Format(TeleConsult.Web.Code.Constants.InvalidFileExtention, sizeLimit));
                                        return View(model);
                                    }
                                }
                                else
                                {
                                    ModelState.AddModelError(
                                        "POCImage",
                                        string.Format(TeleConsult.Web.Code.Constants.MaximumFileLimit, sizeLimit));
                                    return View(model);
                                }
                            }
                        }
                        else
                        {
                            ModelState.AddModelError("POCImage", UiHints.WarningMessageTemplates.RequiredField);
                            return View(model);
                        }
                    }
                    else if ((model.file == null || !model.file.Any()) && (specialization.POCs == null || !specialization.POCs.Any()))
                    {
                        ModelState.AddModelError("POCImage", UiHints.WarningMessageTemplates.RequiredField);
                        return View(model);
                    }
                    //else
                    //{
                    //    ModelState.AddModelError("POCImage", UiHints.WarningMessageTemplates.RequiredField);
                    //    return View(model);
                    //}

                    if (specialization.POCs != null && specialization.POCs.Any())
                    {
                        specialization.POCs = specialization.POCs.Where(p => !p.IsDelete).ToList();
                    }

                    foreach (var country in specialization.lstCountryPermitted)
                    {
                        if (country.StatesAndRegulatories != null)
                        {
                            if (country.StatesAndRegulatories.Any())
                            {
                                var notContainEmptyItem = country.StatesAndRegulatories
                                    .Where(s => !string.IsNullOrWhiteSpace(s.Regulatory)
                                        || !string.IsNullOrWhiteSpace(s.State)).ToList();

                                if (!notContainEmptyItem.Any())
                                {
                                    return View(model);
                                }
                                else
                                {
                                    var statesAndRegulatories = notContainEmptyItem.Where(e =>
                                        !string.IsNullOrWhiteSpace(e.Regulatory)
                                        && !string.IsNullOrWhiteSpace(e.State));
                                    if (statesAndRegulatories.Count() == notContainEmptyItem.Count())
                                    {
                                        country.StatesAndRegulatories = statesAndRegulatories.ToList();
                                    }
                                    else
                                    {
                                        return View(model);
                                    }
                                }
                            }
                            else
                            {
                                return View(model);
                            }
                        }
                    }
                }
                specialization.MinimumCharge = specialization.IsApplyNoMinimumCharge ? 0 : specialization.MinimumCharge;
            }

            var user = Services.Users.GetUserById(id);

            var listProfile = new List<ProfileDto>();

            var profile = Mapper.Map<ProfileViewModel, ProfileDto>(new ProfileViewModel
            {
                Description = model.Description,
                Biography = model.Biography,
                AlternativeEmail = model.AlternativeEmail,
                AlternativeNumber = model.AlternativeNumber,
                Qualification = model.Qualification,
                Languages = model.Languages,
                Avatar = model.AvatarPath,
                ABN = user.Profile.ABN,
                GstRegistered = user.Profile.GstRegistered,
            });
            profile.CreatedDate = DateTime.UtcNow;
            profile.ModifiedDate = DateTime.UtcNow;
            listProfile.Add(profile);

            user.Profiles = listProfile;

            // Create a list Specialization contain list country
            var listSpecialization = new Collection<SpecializationDto>();

            foreach (var item in model.Specializations)
            {
                var Specs = Mapper.Map<SpecializationViewModel, SpecializationDto>(item);

                if (item.LicenceToOperate)
                {
                    var listCountriesPermitted = new List<PermittedCountryDto>();
                    foreach (var country in item.lstCountryPermitted)
                    {
                        string state = "";
                        string regulatory = "";
                        for (int i = 0; i < country.StatesAndRegulatories.Count(); i++)
                        {
                            string tempState = country.StatesAndRegulatories[i].State;
                            string tempRegulatory = country.StatesAndRegulatories[i].Regulatory;

                            if (tempState != null && tempRegulatory != null)
                            {
                                state += tempState + "_";
                                regulatory += tempRegulatory + "_";
                            }
                        }

                        var newCountryPermitted = new PermittedCountryWithoutListStateModel
                        {
                            Name = country.Name,
                            State = state,
                            RegulatoryAuthority = regulatory
                        };

                        var countryPermitted = Mapper.Map<PermittedCountryWithoutListStateModel, PermittedCountryDto>(newCountryPermitted);
                        listCountriesPermitted.Add(countryPermitted);
                    }

                    Specs.PermittedCountries = listCountriesPermitted;
                }

                Specs.CreatedDate = DateTime.UtcNow;
                Specs.ModifiedDate = DateTime.UtcNow;
                listSpecialization.Add(Specs);
            }
            user.Profile.Specializations = listSpecialization;

            // Map list of standard hour
            var listStandardHours = new Collection<WorkingScheduleDto>();
            // Cast a list string to Collection string Standard hour
            foreach (var sdHour in model.ListStandardHour)
            {
                sdHour.CreatedDate = DateTime.UtcNow;
                sdHour.ModifiedDate = DateTime.UtcNow;
                listStandardHours.Add(sdHour);
            }

            user.Profile.WorkingSchedules = listStandardHours;
            user.CompletedStep = Step.Step2;

            if (Services.Users.UpdateUserInfo(user))
            {
                return RedirectToAction("SpecialistRegisterStep3", new { id = id });
            }
            else
            {
                //TODO: show the error message that server cannot save user information
                ViewBag.ErrorMessage("");
                return View(model);
            }
        }
        public ActionResult AddOtherCountryPermitted(SpecialistRegisterStep3ViewModel model, int id)
        {
            RemoveErrorForNewState(model, false, false);

            ViewBag.CultureList = CultureHelper.ListOfCountry();
            if (model.Specializations[id].CountryPermitted == null)
            {
                return Json(new { Success = false }, JsonRequestBehavior.AllowGet);
            }

            string PostedCountryPermit = model.Specializations[id].CountryPermitted;

            //Create an emty list country permitted
            PermittedCountryViewModel CountryPermit = CreateNewCountryPermittedWithState();

            if (model.Specializations[id].lstCountryPermitted == null)
            {
                model.Specializations[id].lstCountryPermitted = new List<PermittedCountryViewModel>();
                model.Specializations[id].lstCountryPermitted.Add(CountryPermit);

                //Add country to list countries
                model.Specializations[id].lstCountryPermitted[0].Name = PostedCountryPermit;
            }
            else
            {
                bool IsCountryPermittedExist = true;

                int numberOfSpecs = model.Specializations.Count();
                for (int i = 0; i < model.Specializations.Count; i++)
                {
                    foreach (var item in model.Specializations[i].lstCountryPermitted)
                    {
                        if (PostedCountryPermit == item.Name)
                        {
                            IsCountryPermittedExist = false;
                            break;
                        }
                    }
                }

                if (IsCountryPermittedExist) //If model already contain country then add an emty StateAndRegulatory
                {
                    for (int i = 0; i < model.Specializations.Count; i++)
                    {
                        foreach (var country in model.Specializations[i].lstCountryPermitted)
                        {
                            int numberOfStateAndRegulatory = country.StatesAndRegulatories.Count();

                            if (country.StatesAndRegulatories[numberOfStateAndRegulatory - 1].State != null &&
                               country.StatesAndRegulatories[numberOfStateAndRegulatory - 1].Regulatory != null)
                            {
                                country.StatesAndRegulatories.Add(new StateAndRegulatory());
                            }
                        }
                    }
                    model.Specializations[id].lstCountryPermitted.Add(CountryPermit);
                    model.Specializations[id].lstCountryPermitted[model.Specializations[id].lstCountryPermitted.Count - 1].Name = PostedCountryPermit;
                }
                else
                {
                    return Json(new { Success = false }, JsonRequestBehavior.AllowGet);
                }
            }

            return View("SpecialistRegisterStep2", model);
        }
        /// <summary>
        /// remove error State is new and don't add on db
        /// </summary>
        /// <param name="model"></param>
        /// <param name="isDelete"></param>
        /// <param name="isCheckMinimumState"></param>
        public void RemoveErrorForNewState(SpecialistRegisterStep3ViewModel model, bool isDelete = false, bool isCheckMinimumState = true)
        {
            for (int i = 0; i < model.Specializations.Count; i++)
            {
                var specialization = model.Specializations[i];
                if (specialization.lstCountryPermitted != null)
                {
                    bool isCheck = specialization.lstCountryPermitted.Count(x => x.StatesAndRegulatories != null && x.StatesAndRegulatories.Count(s => !s.IsNew) > 0) > 0;
                    for (int j = 0; j < specialization.lstCountryPermitted.Count; j++)
                    {
                        var countryPermitted = specialization.lstCountryPermitted[j];
                        int minimumRequiredState = 1;
                        if (!isCheckMinimumState)
                        {
                            minimumRequiredState = 0;
                        }
                        if (isCheck || countryPermitted.StatesAndRegulatories.Count > minimumRequiredState)
                        {
                            for (int k = 0; k < countryPermitted.StatesAndRegulatories.Count; k++)
                            {
                                var states = countryPermitted.StatesAndRegulatories[k];
                                if (states.IsNew)// && string.IsNullOrWhiteSpace(states.State) && string.IsNullOrWhiteSpace(states.Regulatory))
                                {
                                    ModelState.Remove(string.Format("Specializations[{0}].lstCountryPermitted[{1}].StatesAndRegulatories[{2}].State", i, j, k));
                                    ModelState.Remove(string.Format("Specializations[{0}].lstCountryPermitted[{1}].StatesAndRegulatories[{2}].Regulatory", i, j, k));
                                }
                            }
                            if (isDelete)
                            {
                                countryPermitted.StatesAndRegulatories = countryPermitted.StatesAndRegulatories.Where(x => !x.IsNew).ToList();
                            }
                        }
                    }

                    if (isDelete && (specialization.lstCountryPermitted.Count > 1 || !specialization.LicenceToOperate))
                    {
                        specialization.lstCountryPermitted = specialization.lstCountryPermitted.Where(x => x.StatesAndRegulatories != null && x.StatesAndRegulatories.Count(s => !s.IsNew) > 0).ToList();
                        if (specialization.lstCountryPermitted == null || specialization.lstCountryPermitted.Count == 0)
                        {
                            ViewBag.Index = specialization.ProfessionalOrTrade;
                            ViewBag.WarningMessage = UiHints.WarningMessageTemplates.RequiredField;
                        }
                    }
                }
            }
        }
        public ActionResult SpecialistRegisterStep2(Guid id)
        {
            ViewBag.MaximumSize = Services.SystemConfig.GetValueByKey(TeleConsult.Infrastructure.Core.Const.SystemConfig.FILE_UPLOAD_LIMITS);
            ViewBag.CultureList = CultureHelper.ListOfCountry();

            var user = Services.Users.GetUserById(id);
            ProfileDto profile = user.Profiles.FirstOrDefault();
            if (profile != null)
            {
                var model = new SpecialistRegisterStep3ViewModel();

                if (profile.Specializations != null
                    && profile.Specializations.Any())
                {
                    //Back from step 4
                    //TODO: reverse mapping from domain to view model
                    profile.Specializations = Services.Users.GetByUserId(id);
                    var specialistProfile = SpecialistDetailModelMapper.ModelMapper(user, null, Services);
                    model = specialistProfile.SpecialistDetail;

                    model.Email = user.Email;
                    model.MobilePhone = user.MobilePhone;
                    model.ListOfHours = DateTimeHelper.GetHoursList().ToList();
                    model.SpecialistId = id;
                    return View(model);
                }
                else
                {
                    model.Specializations = new List<SpecializationViewModel> { new SpecializationViewModel() };
                    model.AvatarPath = ConstPath.DefaulAvatar;
                    model.ListStandardHour = new List<WorkingScheduleDto>();
                    model.ListStandardHour = DateTimeHelper.DefaultStandardHour();
                    model.SpecialistId = id;
                    model.Email = user.Email;
                    model.MobilePhone = user.MobileCountryCode + user.MobilePhone;
                    model.ListOfHours = DateTimeHelper.GetHoursList().ToList();
                    return View(model);
                }
            }
            else
            {
                profile = new ProfileDto();
                var model = new SpecialistRegisterStep3ViewModel();

                model.Specializations = new List<SpecializationViewModel> { new SpecializationViewModel() };
                model.Email = user.Email;
                model.MobilePhone = user.MobileCountryCode + user.MobilePhone;
                model.AvatarPath = ConstPath.DefaulAvatar;
                model.ListStandardHour = new List<WorkingScheduleDto>();
                model.ListStandardHour = DateTimeHelper.DefaultStandardHour();
                model.SpecialistId = id;
                return View(model);
            }
        }
        public ActionResult DeleteStateRegulatoryAuthor(SpecialistRegisterStep3ViewModel model, int specsId, int countryPermittedId, int rowStateId)
        {
            ViewBag.CultureList = CultureHelper.ListOfCountry();

            int NumberOfStateRows = model.Specializations[specsId].lstCountryPermitted[countryPermittedId].StatesAndRegulatories.Count();

            if (NumberOfStateRows > 1)
            {
                model.Specializations[specsId].lstCountryPermitted[countryPermittedId].StatesAndRegulatories.RemoveAt(rowStateId);
                return View("SpecialistRegisterStep2", model);
            }

            return Json(new { Success = false }, JsonRequestBehavior.AllowGet);
        }
        public ActionResult DeleteSpecializationField(SpecialistRegisterStep3ViewModel model, int id)
        {
            ViewBag.CultureList = CultureHelper.ListOfCountry();
            if (id > 0)
            {
                model.Specializations.RemoveAt(id);
                ViewData["ListIntervalHours"] = Code.Helpers.DateTimeHelper.GetHoursList().ToList();
                return View("SpecialistRegisterStep3", model);
            }

            return Json(new { Success = false }, JsonRequestBehavior.AllowGet);
        }
        public ActionResult DeleteCountryPermitted(SpecialistRegisterStep3ViewModel model, int specsId, int countryPermittedId)
        {
            RemoveErrorForNewState(model, false, false);
            ViewBag.CultureList = CultureHelper.ListOfCountry();
            if (model.Specializations[specsId].lstCountryPermitted == null)
            {
                return Json(new { Success = false }, JsonRequestBehavior.AllowGet);
            }

            model.Specializations[specsId].lstCountryPermitted.RemoveAt(countryPermittedId);

            return View("SpecialistRegisterStep2", model);
        }
        public ActionResult AddStateAndRegulatoryAuthor(SpecialistRegisterStep3ViewModel model, int specsId, int countryPermittedId, int rowStateId)
        {
            ViewBag.CultureList = CultureHelper.ListOfCountry();

            model.Specializations[specsId].lstCountryPermitted[countryPermittedId].StatesAndRegulatories.Add(new StateAndRegulatory());

            return View("SpecialistRegisterStep2", model);
        }
        public ActionResult AddSpecializationField(SpecialistRegisterStep3ViewModel model)
        {
            int numberOfSpecsItem = model.Specializations.Count();
            if (model.Specializations[numberOfSpecsItem - 1].lstCountryPermitted != null)
            {
                int numberOfCoutryPermit = model.Specializations[numberOfSpecsItem - 1].lstCountryPermitted.Count();

                for (int i = 0; i < model.Specializations.Count; i++)
                {
                    foreach (var country in model.Specializations[i].lstCountryPermitted)
                    {
                        int numberOfStateAndRegulatory = country.StatesAndRegulatories.Count();

                        if (country.StatesAndRegulatories[numberOfStateAndRegulatory - 1].State != null &&
                           country.StatesAndRegulatories[numberOfStateAndRegulatory - 1].Regulatory != null)
                        {
                            country.StatesAndRegulatories.Add(new StateAndRegulatory());
                        }
                    }
                }

                var EmtySpecs = new SpecializationViewModel();

                PermittedCountryViewModel CountryPermit = CreateNewCountryPermittedWithState();

                model.Specializations.Add(EmtySpecs);

                return View("SpecialistRegisterStep3", model);
            }
            else
            {
                return Json(new { Success = false }, JsonRequestBehavior.AllowGet);
            }
        }