/// <summary>
        /// Deletes token from database
        /// </summary>
        /// <param name="token"></param>
        public void DeleteToken(string token, long userId)
        {
            try
            {
                using (var dbCtx = new WeatherAppDbEntities())
                {
                    //var singleOrDefault = dbCtx.DeviceInfo.SingleOrDefault(info => info.token == token);

                    //var userId = dbCtx.SendInfo.FirstOrDefault(info => info.UserName == userName).Id;

                    var singleOrDefault = dbCtx.DeviceInfo.SingleOrDefault(info => info.userId == userId && info.token == token);

                    if (singleOrDefault != null)
                    {
                        dbCtx.DeviceInfo.Remove(singleOrDefault);
                        dbCtx.SaveChanges();

                        logger.InfoFormat(string.Format("Token {0} successfully removed from database", token));
                    }
                    else
                    {
                        logger.InfoFormat(string.Format("Token {0} is already removed from database", token));
                        throw new DaoException(string.Format("Token {0} is already removed from database", token));
                    }
                }
            }
            catch (Exception e)
            {
                throw new DaoException(string.Format("Error deleting device token {0}. {1}.", token, e.Message), e);
            }
        }
        public SendInfo Update(SendInfo sendInfo)
        {
            SendInfo result = null;
            try
            {
                using (var dbCtx = new WeatherAppDbEntities())
                {
                    result = dbCtx.SendInfo.SingleOrDefault(info => info.UserName == sendInfo.UserName);

                    if (result != null)
                    {
                        result.Merge(sendInfo);
                        dbCtx.SaveChanges();

                        return result;
                    }
                    else
                        throw new DaoException("No user " + sendInfo.UserName + " found in database");
                }
            }
            catch (Exception e)
            {
                throw new DaoException("Error updating user " + sendInfo.UserName + " in database. " + e.Message, e);
            }
        }
        public Recommendation Update(Recommendation rec)
        {
            Recommendation result = null;
            try
            {
                using (var dbCtx = new WeatherAppDbEntities())
                {
                    result = dbCtx.Recommendations.SingleOrDefault(info => info.GroupItemId == rec.GroupItemId);

                    if (result != null)
                    {
                        result.Condition = rec.Condition;
                        result.Forecast = rec.Forecast;
                        result.Language = rec.Language;
                        result.MelanomaRiskId = rec.MelanomaRiskId;
                        result.VitaminDId = rec.VitaminDId;
                        dbCtx.SaveChanges();

                        return result;
                    }
                    else
                        throw new DaoException("No recommendation groupId" + rec.GroupItemId + " found in database");
                }
            }
            catch (Exception e)
            {
                throw new DaoException("Error updating recommendation " + rec.GroupItemId + " in database. " + e.Message, e);
            }
        }
        /// <summary>
        /// Exact implementation for searching for PR on given weather/melanoma risk/vitd status.
        /// </summary>
        /// <param name="weatherCondition"></param>
        /// <param name="risk"></param>
        /// <param name="vitD"></param>
        /// <returns></returns>
        private List<ForecastResponse> GetRecommendationImpl(ForecastRequest [] request, string risk, bool vitD, string userName, int appId)
        {
            List<ForecastResponse> list = new List<ForecastResponse>();

            using (WeatherAppDbEntities db = new WeatherAppDbEntities())
            {
                var vitDId = db.VitaminDs.Where(con => con.Type == vitD).Select(info => info.Id).FirstOrDefault();
                var melanomaRiskId = db.MelanomaRisks.Where(con => con.Type == risk).Select(info => info.Id).FirstOrDefault();
                var userId = db.SendInfo.Where(con => con.UserName == userName).Select(info => info.Id).FirstOrDefault();

                var appTypeId =
                    db.ApplicationNames.Where(app => app.Id == appId).Select(app => app.Id).FirstOrDefault();
                if (appId == 0 || appTypeId == 0)
                   appId = Options.ApplicationName;

                foreach (ForecastRequest req in request)
                {
                    var condId = db.Conditions.Where(con => con.WeatherCond == req.weather).Select(info => info.Id).FirstOrDefault();
                    if (condId == 0)
                        return null;
                    list.Add(new ForecastResponse { gtForecast = factory.GetSendForecastDao().StorageProcetureCalling(req.date, condId, vitDId, melanomaRiskId, userId, appId), date = req.date.ToString() } );
                }

                var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
                logger.Info(string.Format("Inputs: [ForecastRequest = {0}, Risk = {1}, vitaminD = {2} ] for user {3}", serializer.Serialize(request), risk , vitD, userName));

                logger.Info(string.Format("Outputs: GT forecast [{0}]", string.Join(",", serializer.Serialize(list) )));

                return list;
            }
        }
 public long GetUserIdByName(string userName)
 {
     using (var dbCtx = new WeatherAppDbEntities())
     {
         return dbCtx.SendInfo.FirstOrDefault(info => info.UserName == userName).Id;
     }
 }
 public SendInfo GetInfo(string name)
 {
     using (var _ctx = new WeatherAppDbEntities())
     {
         SendInfo _firstOrDefault = _ctx.SendInfo.FirstOrDefault(info => info.UserName == name)
                                    ?? new SendInfo(name);
         return _firstOrDefault;
     }
 }
 /// <summary>
 /// Searches token in database
 /// </summary>
 /// <param name="token"></param>
 /// <returns></returns>
 public DeviceInfo FindToken(string token)
 {
     try
     {
         using (var dbCtx = new WeatherAppDbEntities())
         {
             return dbCtx.DeviceInfo.FirstOrDefault(info => info.token == token);
         }
     }
     catch (Exception e)
     {
         throw new DaoException(string.Format("Error finding device token {0}. {1}", token, e.Message), e);
     }
 }
 public SendInfo Find(string userName)
 {
     try
     {
         using (var dbCtx = new WeatherAppDbEntities())
         {
             return dbCtx.SendInfo.FirstOrDefault(info => info.UserName == userName);
         }
     }
     catch (Exception e)
     {
         throw new DaoException("Error finding user " + userName + " in database. " + e.Message, e);
     }
 }
 public int SelectCount(string userName)
 {
     try
     {
         using (var dbCtx = new WeatherAppDbEntities())
         {
             return dbCtx.UserInfo.Where(info => info.UserName == userName).Select(info => info).Count();
         }
     }
     catch (Exception e)
     {
         throw new DaoException("Error counting user access tokens", e);
     }
 }
 public Recommendation Insert(Recommendation rec)
 {
     try
     {
         using (var dbCtx = new WeatherAppDbEntities())
         {
             dbCtx.Recommendations.Add(rec);
             dbCtx.SaveChanges();
         }
         return rec;
     }
     catch (Exception e)
     {
         throw new DaoException("Error inserting recommendation " + rec.Forecast + " in database", e);
     }
 }
        public SendForecast Find(string userName)
        {
            try
            {
                using (var dbCtx = new WeatherAppDbEntities())
                {
                    var userId = dbCtx.SendInfo.Where(user => user.UserName == userName).Select(user => user.Id).FirstOrDefault();

                    return dbCtx.SendForecasts.Where(rec => rec.UserId == userId).ToList().FirstOrDefault();
                }
            }
            catch (Exception e)
            {
                throw new DaoException("Error finding send forecast info for user" + userName + " in database. " + e.Message, e);
            }
        }
 public SendInfo Insert(SendInfo info)
 {
     try
     {
         using (var dbCtx = new WeatherAppDbEntities())
         {
             dbCtx.SendInfo.Add(info);
             dbCtx.SaveChanges();
         }
         return info;
     }
     catch (Exception e)
     {
         throw new DaoException("Error inserting user " + info.UserName + " in database", e);
     }
 }
        public List<Recommendation> Find(string weatherCondition, string risk, bool vitD)
        {
            try
            {
                using (var dbCtx = new WeatherAppDbEntities())
                {
                    var riskID = dbCtx.MelanomaRisks.Where(r => r.Type == risk).Select(s => s.Id).FirstOrDefault();
                    var vitDID = dbCtx.VitaminDs.Where(v => v.Type == vitD).Select(s => s.Id).FirstOrDefault();
                    var condId = dbCtx.Conditions.Where(v => v.WeatherCond == weatherCondition).Select(s => s.Id).FirstOrDefault();

                    return dbCtx.Recommendations.Where(rec => rec.VitaminDId == vitDID && rec.MelanomaRiskId == riskID && rec.CondId == condId).ToList();
                }
            }
            catch (Exception e)
            {
                throw new DaoException("Error finding recommendations with weather condition" + weatherCondition + " in database. " + e.Message, e);
            }
        }
        /// <summary>
        /// Returns logged in user data
        /// </summary>
        /// <returns></returns>
        public UserInfo GetCurrent()
        {
            if (string.IsNullOrEmpty(userNameOvr))
            {
                var _httpCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
                var _formsAuthenticationTicket = FormsAuthentication.Decrypt(_httpCookie.Value);

                using (var _ctx = new WeatherAppDbEntities())
                {
                    var _id = long.Parse(_formsAuthenticationTicket.UserData);
                    var _userInfo = _ctx.UserInfo.FirstOrDefault(info => info.Id == _id);
                    return _userInfo;
                }
            }
            else
            {
                using (var _ctx = new WeatherAppDbEntities())
                {
                    var _userInfo = _ctx.UserInfo.Where(info => info.UserName == userNameOvr).OrderByDescending(info => info.Id).First();
                    return _userInfo;
                }
            }
        }
        public UserInfo SaveUser(UserInfo info)
        {
            try
            {
                using (var dbCtx = new WeatherAppDbEntities())
                {
                    var firstOrDefault = dbCtx.UserInfo.FirstOrDefault(user => user.UserName == info.UserName);

                    if (firstOrDefault == null)
                    {
                        dbCtx.UserInfo.Add(info);
                        dbCtx.SaveChanges();

                        return info;
                    }

                    return firstOrDefault;
                }
            }
            catch (Exception e)
            {
                throw new DaoException("Error inserting  new user token info " + info, e);
            }
        }
 public void SaveToken(DeviceInfo tokenInfo)
 {
     try
     {
         using (var dbCtx = new WeatherAppDbEntities())
         {
             dbCtx.DeviceInfo.Add(tokenInfo);
             dbCtx.SaveChanges();
         }
     }
     catch (Exception e)
     {
         throw new DaoException(string.Format("Error inserting device token {0}. "+e.Message, tokenInfo.token), e);
     }
 }
        /// <summary>
        /// Checks all users and sends emails/sms/on-site-alerts when appropriate
        /// </summary>
        public void CheckAllAndSendEmails()
        {
            using (var _ctx = new WeatherAppDbEntities())
            {
                var _api = new MandrillApi(Options.MandrillApi);
                var _infos =
                    _ctx.SendInfo.Where(info => (info.SendEmail ?? false) || (info.SendSms ?? false)).ToList();
                foreach (var _info in _infos)
                {
                    var _mode = _info.Temperature ?? TemperatureMode.F;
                    var _rrb = new PersonalizedForecastResultBuilder(_info.UserName, _mode);
                    LogManager.GetLogger(GetType()).Debug("Processing sendInfo:"+_info.Id);
                    if (IsRightTime(_info))
                    {
                        LogManager.GetLogger(GetType()).Debug("Processing sendInfo, time was right:" + _info.Id);
                        var _weatherWorker = new WeatherWorker(_info.UserName);
                        var _forecastRoot = _weatherWorker.GetForecast10(_info.City);
                        LogManager.GetLogger(GetType()).Debug("Received forecast:" + _info.Id);
                        if (string.IsNullOrEmpty(_info.DataFileId))
                            continue;
                        var _jobId = GetJobId(_info);
                        LogManager.GetLogger(GetType()).Debug("Started job:" + _info.Id);

                        var _riskValue = _rrb.GetAppChainResultingRisks(_jobId.Item1.ToString(), _jobId.Item2.ToString());
                        var _alertCode = _forecastRoot.alerts.Count == 0 ? "--" : _forecastRoot.alerts[0].type;

                        var _riskDescription = _rrb.GetPersonalizedRiskDescription(_forecastRoot.forecast.simpleforecast.forecastday[0].conditions, _alertCode, _riskValue, _info.UserName, Options.ApplicationName);
                        var _subj =
                            string.Format("Forecast for " +
                                          DateTime.Now.ToString("dddd MMMM d"));
                        var _city = WeatherWorker.ConvertFromIDToName(_info.City);
                        var _time = _forecastRoot.current_observation.observation_time;
                        var _todayForecast = _mode == TemperatureMode.F ?
                            _forecastRoot.forecast.txt_forecast.forecastday[0].fcttext :
                            _forecastRoot.forecast.txt_forecast.forecastday[0].fcttext_metric;
                        var _currentObservation = _forecastRoot.current_observation.weather + " and " + (_mode == TemperatureMode.F
                                                 ? _forecastRoot.current_observation.temp_f + "F"
                                                 : _forecastRoot.current_observation.temp_c + "C");

                        if (_info.SendSms ?? false)
                        {
                            LogManager.GetLogger(GetType()).Debug("Sending sms:" + _info.Id);
                            SendSmsNotification(_info, _city, _todayForecast, _currentObservation, _riskDescription);
                        }

                        if (notificationService.IsUserSubscribed(_info.Id))
                        {
                            LogManager.GetLogger(GetType()).Debug("Sending push:" + _info.Id);
                            SendPushNotification(_info, _city, _todayForecast, _currentObservation, _riskDescription);
                        }

                        if (_info.SendEmail ?? false)
                        {
                            LogManager.GetLogger(GetType()).Debug("Sending email:" + _info.Id);
                            SendEmailNotification(_info, _city, _todayForecast, _currentObservation, _riskDescription, _forecastRoot, _mode, _api, _subj);
                        }

                        _info.LastSendDt = DateTime.Now;
                        _ctx.SaveChanges();
                    }
                }
            }
        }
 /// <summary>
 /// Updates entry
 /// </summary>
 /// <param name="ui"></param>
 /// <returns></returns>
 public UserInfo UpdateToken(UserInfo ui)
 {
     using (var _ctx = new WeatherAppDbEntities())
     {
         var _userInfo = _ctx.UserInfo.FirstOrDefault(info => info.Id == ui.Id);
         _userInfo.AuthToken = ui.AuthToken;
         _ctx.SaveChanges();
         return _userInfo;
     }
 }
 /// <summary>
 /// Counts user devices
 /// </summary>
 /// <param name="userId"></param>
 /// <returns></returns>
 public int SelectCount(Int64 userId)
 {
     try
     {
         using (var dbCtx = new WeatherAppDbEntities())
         {
             return dbCtx.DeviceInfo.Where(info => info.userId == userId).Select(info => info).Count();
         }
     }
     catch (Exception e)
     {
         throw new DaoException(string.Format("Error counting user device tokens. "+ e.Message), e);
     }
 }
        public Forecast10Root GetForecast10(string city)
        {
            if (!string.IsNullOrEmpty(userName))
            {
                using (var _ctx = new WeatherAppDbEntities())
                {
                    var _si = _ctx.SendInfo.FirstOrDefault(info => info.UserName == userName);
                    if (_si == null)
                    {
                        _si = new SendInfo(userName);
                        _ctx.SendInfo.Add(_si);
                    }
                    if (_si.WeatherUpdateDt.HasValue &&
                        DateTime.Now.Subtract(_si.WeatherUpdateDt.Value).TotalSeconds < WEATHER_UPD_SECONDS
                        && _si.City == city && _si.LastWeatherUpdate != null)
                    {
                        var _deserializeObject = JsonConvert.DeserializeObject<Forecast10Root>(_si.LastWeatherUpdate);
                        if (_deserializeObject.forecast != null)
                            return _deserializeObject;
                    }

                    var _forecast10Impl = GetForecast10Impl(city);
                    if (_forecast10Impl == null)
                        return null;
                    _si.LastWeatherUpdate = JsonConvert.SerializeObject(_forecast10Impl);
                    _si.WeatherUpdateDt = DateTime.Now;
                    _si.City = city;
                    _ctx.SaveChanges();
                    return _forecast10Impl;
                }
            }
            return GetForecast10Impl(city);
        }
 public List<DeviceInfo> Select(long userId)
 {
     try
     {
         using (var dbCtx = new WeatherAppDbEntities())
         {
             return dbCtx.DeviceInfo.Where(info => info.userId == userId).Select(info => info).ToList();
         }
     }
     catch (Exception e)
     {
         throw new DaoException(string.Format("Error selecting device token. "+e.Message), e);
     }
 }
 /// <summary>
 /// Retrieves user tokens
 /// </summary>
 /// <param name="userId"></param>
 /// <param name="deviceType"></param>
 /// <returns></returns>
 public List<string> GetUserTokens(Int64 userId, DeviceType deviceType)
 {
     try
     {
         using (var dbCtx = new WeatherAppDbEntities())
         {
             return dbCtx.DeviceInfo.Where(info => info.userId == userId && info.deviceType == deviceType).Select(info => info.token).ToList();
         }
     }
     catch (Exception e)
     {
         throw new DaoException(string.Format("Error getting device token. "+e.Message), e);
     }
 }
 /// <summary>
 /// Sends email notification on enabling it
 /// </summary>
 /// <param name="name"></param>
 public void SendEmailInvite(string name)
 {
     using (var _ctx = new WeatherAppDbEntities())
     {
         var _firstOrDefault = _ctx.SendInfo.FirstOrDefault(info => info.UserName == name);
         if (_firstOrDefault != null)
         {
             var _api = new MandrillApi(Options.MandrillApi);
             var _sb = new StringBuilder();
             _sb.Append("<p style='text-align:left'>")
                 .AppendFormat(
                     "Genetically tailored email notifications have been successfully enabled for your <a href='{0}' class='external'>Weather My Way +RTP</a> app. You will receive your first personalized weather forecast by the time you wake up tomorrow.",
                     "https://sequencing.com/weather-my-way-rtp")
                 .Append("</p>");
             _sb.Append("<p style='text-align:left'>");
             _sb.AppendFormat("Notification settings may be changed by going to your app.").Append("</p>");
             SendEmail(_api, _firstOrDefault, "Email notifications from weather app", _sb.ToString());
         }
     }
 }
        public void UpdateToken(string oldId, string newId)
        {
            try
            {
                using (var dbCtx = new WeatherAppDbEntities())
                {
                    var singleOrDefault = dbCtx.DeviceInfo.SingleOrDefault(info => info.token == oldId);

                    if (singleOrDefault != null)
                    {
                        singleOrDefault.token = newId;
                        dbCtx.SaveChanges();

                        logger.ErrorFormat("Old Token {0} successfully updated with new {1} ", oldId, newId);
                    }
                    else
                        throw new DaoException(string.Format("No device token {0} found in database. ", oldId));
                }
            }
            catch (Exception e)
            {
                throw new DaoException(string.Format("Error updating device token {0}. {1}", oldId, e.Message), e);
            }
        }