/// <summary>
        /// Imports the achievement instances from V2
        /// </summary>
        /// <param name="achieveTemplateTable">File w/ achievement instance data</param>
        /// <param name="achievePointTemplateTable">Achievement point instance data (to be rolled into achievement)</param>
        /// <param name="delimiter">Delimiter between data</param>
        /// <param name="work">The DB access</param>
        private void ImportAchievementInstances(
			HttpPostedFileBase achieveInstanceTable,
			HttpPostedFileBase achievePointInstanceTable,
			String delimiter,
			UnitOfWork work)
        {
            // Grab the data
            List<Dictionary<String, String>> achieveData = GetDataFromFile(achieveInstanceTable, delimiter);
            if (achieveData == null)
            {
                ModelState.AddModelError("", "Error with Achievement Instance table.  Check Debug Output");
                return;
            }

            List<Dictionary<String, String>> pointData = GetDataFromFile(achievePointInstanceTable, delimiter);
            if (pointData == null)
            {
                ModelState.AddModelError("", "Error with Achievement Point Instance table.  Check Debug Output");
                return;
            }

            // Put points into a dictionary
            Dictionary<int, int[]> pointLookUp = new Dictionary<int, int[]>();
            foreach (Dictionary<String, String> row in pointData)
            {
                int oldID = int.Parse(row["achievement_instanceID"]);
                if (!pointLookUp.ContainsKey(oldID))
                {
                    pointLookUp.Add(oldID, new int[5]);
                }
                pointLookUp[oldID][int.Parse(row["categoryID"])] = int.Parse(row["points"]);
            }

            // Go through each data row
            try
            {
                work.EntityContext.Configuration.AutoDetectChangesEnabled = false;

                foreach (Dictionary<String, String> row in achieveData)
                {
                    // Get the user and achievement
                    ImportedEarnable achieve = GetImportedEarnableByOldID(_achievementMap, row["achievementID"]);
                    ImportedUser user = GetImportedUserByOldID(row["userID"]);
                    ImportedUser assigner = GetImportedUserByOldID(row["assignedbyID"]);
                    if (achieve == null || achieve.NewID == 0 ||
                        user == null || user.NewID == 0)
                        continue;

                    // How many?
                    int count = int.Parse(row["achievementcount"]);
                    if (count == 0)
                        count = 1;

                    // Make multiple if it's repeatable!
                    for (int i = 0; i < count; i++)
                    {
                        achievement_instance instance = new achievement_instance()
                        {
                            achieved_date = DateTime.Parse(row["date_achieved"]),
                            achievement_id = achieve.NewID,
                            assigned_by_id = assigner == null ? user.NewID : assigner.NewID,
                            card_given = Boolean.Parse(row["has_cardbeengiven"]),
                            card_given_date = String.IsNullOrWhiteSpace(row["givenDate"]) ? (DateTime?)null : DateTime.Parse(row["givenDate"]),
                            comments_disabled = false,
                            has_user_content = Boolean.Parse(row["has_usercontent"]),
                            has_user_story = Boolean.Parse(row["has_userstory"]),
                            user_id = user.NewID,
                            globally_assigned = false
                        };

                        if (i == 0)
                        {
                            // Look up points
                            int[] points;
                            if (pointLookUp.TryGetValue(int.Parse(row["achievement_instanceID"]), out points))
                            {
                                instance.points_create = points[1]; // Create = 1
                                instance.points_explore = points[4]; // Explore = 4
                                instance.points_learn = points[2]; // Learn = 2
                                instance.points_socialize = points[3]; // Socialize = 3
                            }

                            // Get user content/story stuff
                            ImportedEarnable userContent = GetImportedEarnableByOldID(_userContentMap, row["usercontentID"]);
                            ImportedEarnable userStory = GetImportedEarnableByOldID(_userStoryMap, row["userstoryID"]);
                            if (instance.has_user_content)
                            {
                                if (userContent == null || userContent.NewID == 0)
                                    continue;	// If content is REQUIRED, and not found, skip this - User will need to re-get achievement
                                else
                                    instance.user_content_id = userContent.NewID;
                            }

                            // Check for legit user story
                            if (instance.has_user_story && userStory != null && userStory.NewID > 0)
                            {
                                instance.user_story_id = userStory.NewID;
                            }

                            if (!instance.has_user_story && instance.has_user_content)
                            {
                                var content = work.EntityContext.achievement_user_content.Local.Single(c => c.id == userContent.NewID);
                                achievement_user_story newStory = new achievement_user_story()
                                {
                                    date_submitted = content.submitted_date,
                                    image = content.image,
                                    text = content.text
                                };
                                work.EntityContext.achievement_user_story.Add(newStory);
                                instance.has_user_story = true;
                                instance.user_story = newStory;
                            }
                        }

                        // Add to the DB
                        work.EntityContext.achievement_instance.Add(instance);
                    }

                }
            }
            finally { work.EntityContext.Configuration.AutoDetectChangesEnabled = true; }

            work.SaveChanges();

            // Update content paths
            try
            {
                work.EntityContext.Configuration.AutoDetectChangesEnabled = false;
                foreach (achievement_instance instance in work.EntityContext.achievement_instance)
                {
                    if (instance.user_content != null)
                    {
                        instance.user_content.image = UpdateContentPath(instance.user_id, instance.user_content.image);
                    }

                    if (instance.user_story != null)
                    {
                        instance.user_story.image = UpdateContentPath(instance.user_id, instance.user_story.image);
                    }
                }
            }
            finally { work.EntityContext.Configuration.AutoDetectChangesEnabled = true; }
            work.SaveChanges();
        }
        //TODO: OPTIMIZE THE WAY ACHIEVEMENTS ARE ASSIGNED TO REDUCE DATABASE QUERIES AND SPEED UP THE OVERALL PROCESS
        /// <summary>
        /// Assigns an achievement
        /// TODO: Put in lots more error checking!
        /// </summary>
        /// <param name="userID">The id of the user getting the achievement</param>
        /// <param name="achievementID">The id of the achievement template</param>
        /// <param name="assignedByID">The id of the user assigning the achievement</param>
        /// <param name="cardGiven">Was the card given to the user?</param>
        public JPPConstants.AssignAchievementResult AssignAchievement(int userID, int achievementID, int? assignedByID = null, bool autoSave = true, DateTime? dateAssigned = null, bool cardGiven = false, bool isGlobal = false)
        {
            //Int value to keep track of whether a repeatable achievement can be awarded or not.
            AchievementInstanceResult instanceResult = AchievementInstanceResult.First;
            // Get the achievement template
            achievement_template template = _dbContext.achievement_template.Find(achievementID);
            // Get the user
            user user = _dbContext.user.Find(userID);

            //Get the assigner
            user assigner = _dbContext.user.Find(assignedByID);

            //Make sure the achievement can be assigned
            #region Validate Parameters
            //Make sure the achievement and user exist
            if (template == null)
                return JPPConstants.AssignAchievementResult.FailureInvalidAchievement;
            if (user == null)
                return JPPConstants.AssignAchievementResult.FailureInvalidPlayer;
            if (assigner == null && assignedByID != null)
                return JPPConstants.AssignAchievementResult.FailureInvalidAssigner;
            //Check to make sure the user is a player, and that they are not suspended,deactivate,deleted
            if (user.status != (int)JPPConstants.UserStatus.Active || !user.is_player)
                return JPPConstants.AssignAchievementResult.FailureUnauthorizedPlayer;
            // Check For Instances
            if (_dbContext.achievement_instance.Any(ai => ai.achievement_id == achievementID && ai.user_id == userID) && !template.is_repeatable)
                return JPPConstants.AssignAchievementResult.FailureAlreadyAchieved;
            //Check to see if the achievement is repeatable, and if so, has the user waited long enough since the last time they received it
            if (template.is_repeatable)
                instanceResult = CanAwardRepeatableAchievement(template, userID);
            if (instanceResult.Equals(AchievementInstanceResult.TooSoon))
                return JPPConstants.AssignAchievementResult.FailureRepetitionDelay;
            #endregion

            // Create the new instance
            achievement_instance newInstance = new achievement_instance()
            {
                achieved_date = dateAssigned == null ? DateTime.Now : (DateTime)dateAssigned,
                achievement_id = achievementID,
                assigned_by_id = assignedByID.HasValue ? assignedByID.Value : userID,
                card_given = cardGiven,
                card_given_date = cardGiven ? (Nullable<DateTime>)DateTime.Now : null,
                comments_disabled = false,
                has_user_content = false,
                has_user_story = false,
                points_create = instanceResult.Equals(AchievementInstanceResult.Repeat) ? 0 : template.points_create,
                points_explore = instanceResult.Equals(AchievementInstanceResult.Repeat) ? 0 : template.points_explore,
                points_learn = instanceResult.Equals(AchievementInstanceResult.Repeat) ? 0 : template.points_learn,
                points_socialize = instanceResult.Equals(AchievementInstanceResult.Repeat) ? 0 : template.points_socialize,
                user_content_id = null,
                user_id = userID,
                user_story_id = null,
                globally_assigned = isGlobal,
            };
            // Add the instance to the database
            _dbContext.achievement_instance.Add(newInstance);
            _unitOfWork.SystemRepository.AddNotification(
                userID,
                newInstance.assigned_by_id,
                "You earned the achievement [" + template.title + "]",
                template.icon,
                new UrlHelper(HttpContext.Current.Request.RequestContext).Action(
                    "IndividualAchievement",
                    "Achievements",
                    new { id = template.id }
                ) + "#" + newInstance.id,
                false);

            #region Facebook Sharing
            bool facebookEnabledOnSite = bool.Parse(JPPConstants.SiteSettings.GetValue(JPPConstants.SiteSettings.FacebookIntegrationEnabled));
            if (facebookEnabledOnSite)
            {
                facebook_connection fbConnectionData = _unitOfWork.UserRepository.GetUserFacebookSettingsById(userID);
                if (fbConnectionData != null)
                {
                    string appNamespace = JPPConstants.SiteSettings.GetValue(JPPConstants.SiteSettings.FacebookAppNamespace);
                    UrlHelper urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
                    string achievementUri = JppUriInfo.GetAbsoluteUri(new HttpRequestWrapper(HttpContext.Current.Request),
                        urlHelper.RouteUrl("AchievementsPlayersRoute", new { id = achievementID })
                        );
                    string relativeEarnedAchievementUri = urlHelper.RouteUrl("AchievementsPlayersRoute", new { id = achievementID, playerID = userID });

                    try
                    {
                        FacebookClient fbClient = new FacebookClient();

                        // Cannot send notifications unless we're a canvas app. Code implemented,
                        // but will return an OAuth error
                        /*
                        if (fbConnectionData.notifications_enabled)
                        {
                            string appAccessToken = JppFacebookHelper.GetAppAccessToken(fbClient);

                            fbClient.Post("/" + fbConnectionData.facebook_user_id + "/notifications", new
                            {
                                access_token = appAccessToken,
                                template = JPPConstants.GetFacebookNotificationMessage(template.title),
                                href = VirtualPathUtility.ToAbsolute(relativeEarnedAchievementUri),
                            });
                        }//*/

                        if (fbConnectionData.automatic_sharing_enabled)
                        {
                            fbClient.Post("/me/" + appNamespace + ":earn", new
                            {
                                access_token = fbConnectionData.access_token,
                                achievement = achievementUri
                            });
                        }
                    }
                    catch (FacebookOAuthException e)
                    {
                        // TODO: log FB error
                    }
                }
            }
            #endregion

            JPPConstants.AssignAchievementResult result = JPPConstants.AssignAchievementResult.Success;

            if (Convert.ToBoolean(JPPConstants.SiteSettings.GetValue(JPPConstants.SiteSettings.CardDistributionEnabled)))
            {
                if (cardGiven)
                {
                    result = JPPConstants.AssignAchievementResult.SuccessYesCard;
                    LoggerModel logCard = new LoggerModel()
                    {
                        Action = Logger.AchievementInstanceLogType.CardGiven.ToString(),
                        IPAddress = HttpContext.Current.Request.UserHostAddress,
                        UserID = newInstance.assigned_by_id,
                        TimeStamp = (DateTime)newInstance.card_given_date,
                        ID1 = newInstance.achievement_id,
                        IDType1 = Logger.LogIDType.AchievementTemplate.ToString(),
                    };
                    Logger.LogSingleEntry(logCard, _dbContext);
                }
                else
                    result = JPPConstants.AssignAchievementResult.SuccessNoCard;
            }

            if (template.is_repeatable)
            {
                result = JPPConstants.AssignAchievementResult.SuccessRepetition;

                if (CheckForThresholdUnlock(achievementID, userID))
                    result = JPPConstants.AssignAchievementResult.SuccessThresholdTriggered;
            }

            if (!isGlobal)
            {
                List<achievement_instance> userAchievements = _dbContext.achievement_instance.Where(ai => ai.user_id == userID).ToList().Union(_dbContext.achievement_instance.Local.Where(ai => ai.user_id == userID).ToList()).ToList();
                _unitOfWork.QuestRepository.CheckAssociatedQuestCompletion(achievementID, user, userAchievements, autoSave);
                CheckRingSystemAchievements(userID, userAchievements);
                CheckOneKAndTenKSystemAchievements(userID);
            }

            if (autoSave)
                Save();

            return result;
        }
        public void AwardCard(achievement_instance instance)
        {
            if (!instance.card_given)
            {
                LoggerModel logCard = new LoggerModel()
                {
                    Action = Logger.AchievementInstanceLogType.CardGiven.ToString(),
                    UserID = WebSecurity.CurrentUserId,
                    IPAddress = HttpContext.Current.Request.UserHostAddress,
                    TimeStamp = DateTime.Now,
                    IDType1 = Logger.LogIDType.User.ToString(),
                    ID1 = instance.user_id,
                    IDType2 = Logger.LogIDType.AchievementTemplate.ToString(),
                    ID2 = instance.achievement_template.id
                };
                instance.card_given_date = DateTime.Now;
                instance.card_given = true;
            }

            Save();
        }
        public void RevokeCard(achievement_instance instance)
        {
            if (instance.card_given)
                instance.card_given_date = null;
            instance.card_given = false;

            Save();
        }