public async Task <IActionResult> AddNotification(PushNotificationModel model)
        {
            if (!await _permissionService.AuthorizeAsync(StandardPermissionProvider.ManagePushNotification))
            {
                return(AccessDeniedView());
            }

            PushNotification pushNotification = new PushNotification();

            #region Validation

            //validate stores
            var allStores = await _storeService.GetStores();

            var newStores = new List <Store>();
            foreach (var store in allStores)
            {
                if (model.SelectedStoreIds.Contains(store.P_BranchNo))
                {
                    newStores.Add(store);
                }
            }

            if (!model.SelectedNotificationCategoryIds.Any())
            {
                _notificationService.ErrorNotification("Category is required");
                model = await _pushNotificationModelFactory.PreparePushNotificationModel(model, pushNotification);

                model = GetStore(model);
                model = GetRepeat(model);
                model.SelectedNotificationCategoryIds = new List <int?>();

                return(View(model));
            }
            else if (model.SelectedNotificationCategoryIds.Count() == 1)
            {
                var catId = model.SelectedNotificationCategoryIds.FirstOrDefault();
                if (catId == null)
                {
                    _notificationService.ErrorNotification("Category is required");
                    model = await _pushNotificationModelFactory.PreparePushNotificationModel(model, pushNotification);

                    model = GetStore(model);
                    model = GetRepeat(model);
                    model.SelectedNotificationCategoryIds = new List <int?>();

                    return(View(model));
                }
            }

            if (model.SelectedNotificationCategoryIds.FirstOrDefault() == 1)
            {
                if (model.SelectedStockTake == null)
                {
                    _notificationService.ErrorNotification("Stock Take # is required");
                    model = await _pushNotificationModelFactory.PreparePushNotificationModel(model, pushNotification);

                    model             = GetStore(model);
                    model             = GetRepeat(model);
                    model.StockTakeNo = null;

                    return(View(model));
                }
                else if (model.SelectedStockTake != null && model.SelectedStockTake.Count() == 1)
                {
                    if (model.SelectedStockTake.FirstOrDefault() == null)
                    {
                        _notificationService.ErrorNotification("Stock Take # is required");
                        model = await _pushNotificationModelFactory.PreparePushNotificationModel(model, pushNotification);

                        model             = GetStore(model);
                        model             = GetRepeat(model);
                        model.StockTakeNo = null;

                        return(View(model));
                    }
                    else
                    {
                        model.StockTakeNo = model.SelectedStockTake.FirstOrDefault();
                    }
                }
                else
                {
                    model.StockTakeNo = model.SelectedStockTake.FirstOrDefault();
                }
            }
            else
            {
                model.StockTakeNo = null;

                if (model.SelectedStoreIds.Count == 0)
                {
                    _notificationService.ErrorNotification("Store is required");
                    model = await _pushNotificationModelFactory.PreparePushNotificationModel(model, pushNotification);

                    model.SelectedStoreIds = new List <int>();

                    return(View(model));
                }
            }

            #endregion

            if (ModelState.IsValid)
            {
                try
                {
                    DateTime currentTime = DateTime.Now;

                    pushNotification.Title                  = model.Title;
                    pushNotification.Desc                   = model.Description;
                    pushNotification.StockTakeNo            = model.StockTakeNo == null ? 0 : model.StockTakeNo;
                    pushNotification.NotificationCategoryId = Convert.ToInt32(model.SelectedNotificationCategoryIds.FirstOrDefault());
                    pushNotification.Interval               = model.RemindMe ? model.SelectedRepeat : null;
                    pushNotification.RemindMe               = model.RemindMe;
                    pushNotification.StartTime              = model.RemindMe ? model.StartTime : null;
                    pushNotification.EndTime                = model.RemindMe ? model.EndTime : null;

                    if (model.SelectedNotificationCategoryIds.FirstOrDefault() == 1)
                    {
                        model.SelectedStoreIds = new List <int>();
                        List <StockTakeHeader> stList = GetStockTakeStore(model.StockTakeNo);
                        foreach (var parent in stList)
                        {
                            foreach (var child in parent.Stores)
                            {
                                model.SelectedStoreIds.Add(Convert.ToInt32(child.StoreNo));
                            }
                        }
                    }

                    //stores
                    List <PushNotificationStore> pushNotificationStoreList = new List <PushNotificationStore>();
                    pushNotification.PushNotificationStores = new List <PushNotificationStore>();

                    List <PushNotificationDevice> pushNotificationDeviceList = new List <PushNotificationDevice>();
                    pushNotification.PushNotificationDevices = new List <PushNotificationDevice>();
                    int i = 0;

                    foreach (var item in model.SelectedStoreIds)
                    {
                        if (allStores.Any(x => x.P_BranchNo == item))
                        {
                            i = 0;
                            PushNotificationStore pushNotificationStore =
                                new PushNotificationStore
                            {
                                PushNotificationId = pushNotification.Id,
                                StoreId            = item
                            };
                            pushNotification.PushNotificationStores.Add(pushNotificationStore);

                            //device
                            var deviceResult = _deviceModelFactory.PrepareDeviceListbyStoreModel(item);

                            if (deviceResult.Result?.Devices?.Count > 0)
                            {
                                foreach (var devices in deviceResult.Result.Devices)
                                {
                                    i++;
                                    PushNotificationDevice pushNotificationDevice =
                                        new PushNotificationDevice
                                    {
                                        PushNotificationId = pushNotification.Id,
                                        JobName            = model.RemindMe ? "Job" + currentTime.ToString("ddMMyyyyHHmmssfff") + i : null,
                                        JobGroup           = model.RemindMe ? "Group" + currentTime.ToString("ddMMyyyyHHmmssfff") + i : null,
                                        DeviceId           = devices.Id
                                    };
                                    pushNotification.PushNotificationDevices.Add(pushNotificationDevice);
                                }
                            }
                        }
                        else if (item == -99) //All stores
                        {
                            i = 0;
                            foreach (var store in allStores)
                            {
                                PushNotificationStore pushNotificationStore =
                                    new PushNotificationStore
                                {
                                    PushNotificationId = pushNotification.Id,
                                    StoreId            = store.P_BranchNo
                                };
                                pushNotification.PushNotificationStores.Add(pushNotificationStore);
                            }
                            //device
                            var deviceResult = _deviceModelFactory.PrepareDeviceListbyStoreModel(item);

                            if (deviceResult.Result?.Devices?.Count > 0)
                            {
                                foreach (var devices in deviceResult.Result.Devices)
                                {
                                    i++;
                                    PushNotificationDevice pushNotificationDevice =
                                        new PushNotificationDevice
                                    {
                                        PushNotificationId = pushNotification.Id,
                                        JobName            = model.RemindMe ? "Job" + currentTime.ToString("ddMMyyyyHHmmssfff") + i : null,
                                        JobGroup           = model.RemindMe ? "Group" + currentTime.ToString("ddMMyyyyHHmmssfff") + i : null,
                                        DeviceId           = devices.Id
                                    };
                                    pushNotification.PushNotificationDevices.Add(pushNotificationDevice);
                                }
                            }
                        }
                    }

                    await _pushNotificationService.InsertPushNotification(pushNotification);

                    _notificationService.SuccessNotification("Push Notification has been added successfully.");

                    //selected tab
                    SaveSelectedTabName();

                    //Others
                    if (model.RemindMe)
                    {
                        string title = string.Empty;
                        if (pushNotification.StockTakeNo != 0)
                        {
                            title = model.Title + "(Stock Take #" + pushNotification.StockTakeNo + ")";
                        }
                        else
                        {
                            title = model.Title;
                        }

                        foreach (var item in pushNotification.PushNotificationDevices)
                        {
                            if (item.Device != null && !string.IsNullOrEmpty(item.Device.TokenId))
                            {
                                //why not use IScheduledTask? this is repetitive = performance.
                                Scheduler.Start(
                                    item.JobName,
                                    item.JobGroup,
                                    model.Title,
                                    model.Description,
                                    item.Device.TokenId,
                                    model.StartTime.GetValueOrDefault(),
                                    model.EndTime.GetValueOrDefault().Add(new TimeSpan(23, 59, 59)),
                                    model.SelectedRepeat,
                                    _iconfiguration["APIKey"].ToString()
                                    /*,_iconfiguration["FirebaseSenderID"].ToString()*/); //not required
                            }
                        }
                    }

                    return(RedirectToAction("Index"));
                }
                catch (Exception e)
                {
                    _notificationService.ErrorNotification(e.Message);
                }
            }

            model = await _pushNotificationModelFactory.PreparePushNotificationModel(model, pushNotification);

            return(View(model));
        }
        public async Task <IActionResult> EditNotification(PushNotificationModel model, bool continueEditing)
        {
            if (!await _permissionService.AuthorizeAsync(StandardPermissionProvider.ManagePushNotification))
            {
                return(AccessDeniedView());
            }

            var pushNotification = await _pushNotificationService.GetPushNotificationByIdAsync(model.Id);

            if (pushNotification == null)
            {
                return(RedirectToAction("Index"));
            }

            #region Validation

            //validate stores
            var allStores = await _storeService.GetStores();

            var newStores = new List <Store>();
            foreach (var store in allStores)
            {
                if (model.SelectedStoreIds.Contains(store.P_BranchNo))
                {
                    newStores.Add(store);
                }
            }

            if (model.SelectedNotificationCategoryIds.Count() == 0)
            {
                _notificationService.ErrorNotification("Category is required");
                model = await _pushNotificationModelFactory.PreparePushNotificationModel(model, pushNotification);

                model.SelectedNotificationCategoryIds = new List <int?>();

                return(View(model));
            }
            else
            {
                if (model.SelectedNotificationCategoryIds.FirstOrDefault() == 1)
                {
                    model.StockTakeList          = GetStockTakeStore(null);
                    model.AvailableStockTakeList = model.StockTakeList.Select(stList => new SelectListItem
                    {
                        Text  = stList.StockTakeNo,
                        Value = stList.StockTakeNo
                    }).ToList();

                    if (model.AvailableStockTakeList.Count > 0 && model.SelectedStockTake == null)
                    {
                        _notificationService.ErrorNotification("Stock Take # is required");
                        model = await _pushNotificationModelFactory.PreparePushNotificationModel(model, pushNotification);

                        model.StockTakeNo = null;

                        return(View(model));
                    }

                    model.StockTakeNo = model.SelectedStockTake.FirstOrDefault();
                }
                else
                {
                    model.StockTakeNo = null;

                    if (model.SelectedStoreIds.Count == 0)
                    {
                        _notificationService.ErrorNotification("Store is required");
                        model = await _pushNotificationModelFactory.PreparePushNotificationModel(model, pushNotification);

                        model.SelectedStoreIds = new List <int>();

                        return(View(model));
                    }
                }
            }

            #endregion

            if (ModelState.IsValid)
            {
                try
                {
                    DateTime currentTime = DateTime.Now;

                    //Delete existing job and recreate later
                    IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler().Result;
                    if (pushNotification.RemindMe)
                    {
                        if (pushNotification.PushNotificationDevices != null)
                        {
                            foreach (var item in pushNotification.PushNotificationDevices)
                            {
                                if (await scheduler.CheckExists(new JobKey(item.JobName, item.JobGroup)))
                                {
                                    await scheduler.DeleteJob(new JobKey(item.JobName, item.JobGroup));
                                }
                            }
                        }
                    }

                    pushNotification.Title                  = model.Title;
                    pushNotification.Desc                   = model.Description;
                    pushNotification.StockTakeNo            = model.StockTakeNo == null ? 0 : model.StockTakeNo;
                    pushNotification.NotificationCategoryId = (int)model.SelectedNotificationCategoryIds.FirstOrDefault();
                    pushNotification.RemindMe               = model.RemindMe;
                    pushNotification.Interval               = model.RemindMe ? model.SelectedRepeat : null;
                    pushNotification.StartTime              = model.RemindMe ? model.StartTime : null;
                    pushNotification.EndTime                = model.RemindMe ? model.EndTime : null;

                    if (model.SelectedNotificationCategoryIds.FirstOrDefault() == 1)
                    {
                        model.SelectedStoreIds = new List <int>();
                        List <StockTakeHeader> stList = GetStockTakeStore(model.StockTakeNo);
                        foreach (var parent in stList)
                        {
                            foreach (var child in parent.Stores)
                            {
                                model.SelectedStoreIds.Add(Convert.ToInt32(child.StoreNo));
                            }
                        }
                    }

                    //stores
                    List <PushNotificationStore>  pushNotificationStoreList  = new List <PushNotificationStore>();
                    List <PushNotificationDevice> pushNotificationDeviceList = new List <PushNotificationDevice>();
                    List <Tuple <int, string> >   deleteList = new List <Tuple <int, string> >();


                    int i = 0;

                    foreach (var item in pushNotification.PushNotificationStores)
                    {
                        if (!model.SelectedStoreIds.Any(x => x == item.StoreId))
                        {
                            // add an item
                            deleteList.Add(new Tuple <int, string>(model.Id, item.StoreId.ToString()));
                        }
                    }
                    if (deleteList != null && deleteList.Count > 0)
                    {
                        foreach (var deleteItem in deleteList)
                        {
                            //remove store
                            _pushNotificationService.DeletePushNotificationStore(deleteItem.Item1, Convert.ToInt32(deleteItem.Item2));
                        }
                    }

                    foreach (var item in model.SelectedStoreIds)
                    {
                        if (allStores.Any(x => x.P_BranchNo == item))
                        {
                            //new store
                            if (pushNotification.PushNotificationStores.Count(mapping => mapping.StoreId == item) == 0)
                            {
                                i = 0;
                                PushNotificationStore pushNotificationStore =
                                    new PushNotificationStore
                                {
                                    PushNotificationId = pushNotification.Id,
                                    StoreId            = item
                                };

                                pushNotification.PushNotificationStores.Add(pushNotificationStore);

                                //device
                                var deviceResult = _deviceModelFactory.PrepareDeviceListbyStoreModel(item);

                                if (deviceResult.Result?.Devices?.Count > 0)
                                {
                                    foreach (var devices in deviceResult.Result.Devices)
                                    {
                                        i++;
                                        PushNotificationDevice pushNotificationDevice =
                                            new PushNotificationDevice
                                        {
                                            PushNotificationId = pushNotification.Id,
                                            JobName            = model.RemindMe ? "Job" + currentTime.ToString("ddMMyyyyHHmmssfff") + i : null,
                                            JobGroup           = model.RemindMe ? "Group" + currentTime.ToString("ddMMyyyyHHmmssfff") + i : null,
                                            DeviceId           = devices.Id
                                        };
                                        pushNotification.PushNotificationDevices.Add(pushNotificationDevice);
                                    }
                                }
                            }
                        }
                    }

                    _pushNotificationService.UpdatePushNotification(pushNotification);

                    _notificationService.SuccessNotification("Push Notification has been updated successfully.");

                    //selected tab
                    SaveSelectedTabName();

                    //Others
                    if (model.RemindMe)
                    {
                        foreach (var item in pushNotification.PushNotificationDevices)
                        {
                            if (item.Device != null && !string.IsNullOrEmpty(item.Device.TokenId))
                            {
                                //why not use IScheduledTask? this is repetitive = performance.
                                Scheduler.Start(
                                    item.JobName,
                                    item.JobGroup,
                                    model.Title,
                                    model.Description,
                                    item.Device.TokenId,
                                    model.StartTime.Value,
                                    model.EndTime.Value.Add(new TimeSpan(23, 59, 59)),
                                    model.SelectedRepeat,
                                    _iconfiguration["APIKey"].ToString());
                            }
                        }
                    }

                    if (!continueEditing)
                    {
                        return(RedirectToAction("Index"));
                    }

                    return(RedirectToAction("EditNotification", new { id = pushNotification.Id }));
                }
                catch (Exception e)
                {
                    _notificationService.ErrorNotification(e.Message);
                }
            }

            model = await _pushNotificationModelFactory.PreparePushNotificationModel(model, pushNotification);

            return(View(model));
        }