public static void Main()
        {
            callGraphServiceTimer.Start();
            callGraphServiceTimer.Elapsed += (sender, e) => HandleTimer(sender, e);

            ViaNettSMS viaNettSMS = new ViaNettSMS(_SMSServiceUserName, _SMSServicePassword);

            try
            {
                // ADAL: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-libraries
                authenticationContext = new AuthenticationContext(GraphService.DefaultAadInstance, TokenCache.DefaultShared);

                authenticationResult = authenticationContext.AcquireTokenAsync(
                    GraphService.ResourceId,
                    _ApplicationAppId,
                    _ApplicationRedirectUri,
                    new PlatformParameters(PromptBehavior.RefreshSession)).Result;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }


            // This BookingsContainer is generated by the ODATA v4 Client Code Generator
            // See https://odata.github.io and https://github.com/odata/odata.net for usage.
            // Note that the code generator customizes the entity and property names to PascalCase
            // so they match C# guidelines, while the EDM uses lower case camelCase, as per Graph guidelies.
            // Since the application is short lived, the delegate is simply returning the authorization
            // header obtained above; a long lived application would likely need to refresh the token
            // when it expires, so it would have a slightly more complex delegate.

            var graphService = new GraphService(
                GraphService.DefaultV1ServiceRoot,
                () =>
            {
                // Hvis Token timedout
                // Forny Token
                if (authenticationResult.ExpiresOn.ToLocalTime() >= DateTime.Now)
                {
                    //refresh
                    // Har mulighet til å refreshe i 5 minutter etter token har utgått
                    authenticationResult = authenticationContext.AcquireTokenSilentAsync(GraphService.ResourceId, _ApplicationAppId).Result;
                    string _header       = authenticationResult.CreateAuthorizationHeader();
                    return(_header);
                }
                else
                {
                    string _header = authenticationResult.CreateAuthorizationHeader();
                    return(_header);
                }
            });



            // Fiddler makes it easy to look at the request/response payloads. Use it automatically if it is running.
            // https://www.telerik.com/download/fiddler
            if (System.Diagnostics.Process.GetProcessesByName("fiddler").Any())
            {
                graphService.WebProxy = new WebProxy(new Uri("http://*****:*****@"[^\d+]", ""),
                            customerNotes        = oDataAppointment.CustomerNotes,
                            Id             = oDataAppointment.Id,
                            staffMemberIds = oDataAppointment.StaffMemberIds.FirstOrDefault(),
                            Start          = System.DateTime.Parse(oDataAppointment.Start.DateTime).ToLocalTime(),
                            End            = System.DateTime.Parse(oDataAppointment.End.DateTime).ToLocalTime(),
                            serviceId      = oDataAppointment.ServiceId,
                            serviceName    = oDataAppointment.ServiceName.ToLower(),
                            json           = JsonConvert.SerializeObject(oDataAppointment),
                            md5            = Convert.ToBase64String(md5.ComputeHash(Encoding.UTF8.GetBytes(oDataAppointment.Id + oDataAppointment.Start.DateTime.ToString() + oDataAppointment.End.DateTime.ToString()))),
                            md5hash        = md5.ComputeHash(Encoding.Unicode.GetBytes(oDataAppointment.Id))
                        };


                        Debug.WriteLine(appointment.json);

                        List <BookingAppointment> _list = new List <BookingAppointment>
                        {
                            oDataAppointment
                        };

                        switch (InsertOrUpdate(appointment, db))
                        {
                        case EntityState.Detached:
                            break;

                        case EntityState.Unchanged:
                            break;

                        case EntityState.Added:
                            // Ny Avtale
                            SendSMS(viaNettSMS, _business, _list, SMSTemplate.SMSConfirmation);
                            break;

                        case EntityState.Deleted:
                            break;

                        case EntityState.Modified:
                            // Avtalen er endret
                            SendSMS(viaNettSMS, _business, _list, SMSTemplate.SMSUpdate);
                            break;

                        default:
                            break;
                        }
                    }

                    //Create a list of Cancelled Appointments (Appointments in database not occuring from the graphservice.business.appointments )
                    List <byte[]> odataIDs;
                    try
                    {
                        odataIDs = bookingAppointments.Select(x => md5.ComputeHash(Encoding.Unicode.GetBytes(x.Id))).ToList <byte[]>();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"ExceptionCount: {exceptionCount}  , exception: {e.InnerException.ToString()}");
                        exceptionCount++;
                        continue;
                    }

                    /*
                     *
                     */

                    var deleteAppointments = from a in db.Appointment
                                             where !odataIDs.Contains(a.md5hash) && a.Start > DateTime.Now &&
                                             a.appointmentIsActive == true
                                             select a;

                    var bookingAppointmentList = new List <BookingAppointment>();

                    //Update database for every Cancelled appointment and create a list of those Appointments
                    foreach (var appoint in deleteAppointments)
                    {
                        appoint.appointmentIsActive    = false;
                        appoint.appointmentChangedDate = DateTime.Now;

                        var bappoint = JsonConvert.DeserializeObject <BookingAppointment>(appoint.json);
                        bookingAppointmentList.Add(bappoint);
                    }

                    try
                    {
                        db.SaveChanges();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine($"ExceptionCount: {exceptionCount}  , exception: {e.InnerException.ToString()}");
                        exceptionCount++;
                        continue;
                    }

                    /* Send SMS for every Cancelled Appointments in the AppointmentList*/
                    SendSMS(viaNettSMS, _business, bookingAppointmentList, SMSTemplate.SMSCancellation);


                    // Send Reminder SMS
                    DateTime rm1DateTimeMax = DateTime.Now.Add(SMSReminder1TimeSpanBefore);
                    DateTime rm2DateTimeMax = DateTime.Now.Add(SMSReminder2TimeSpanBefore);
                    //DateTime rm3DateTimeMax = DateTime.Now.Add(SMSReminder3TimeSpanBefore);
                    DateTime rm1DateTimeMin = rm1DateTimeMax.AddHours(-2);
                    DateTime rm2DateTimeMin = rm2DateTimeMax.AddHours(-2);
                    //DateTime rm3DateTimeMin = rm3DateTimeMax.AddHours(-2);
                    DateTime surveyDateTimeMin = DateTime.Now.Add(SMSSurveyTimeSpanBefore);


                    // 7 Dager
                    var reminder1Appointments = from a in db.Appointment
                                                where a.SMSLog.Where(s => s.smsTemplate == SMSTemplate.SMSReminder1.ToString() && s.smsIsSent == true).Count() < 1 &&
                                                a.Start <rm1DateTimeMax &&
                                                         a.Start> rm1DateTimeMin &&
                                                !(a.appointmentCreatedDate <rm1DateTimeMax && a.appointmentCreatedDate> rm1DateTimeMin) &&
                                                !string.IsNullOrEmpty(a.customerId) &&
                                                !string.IsNullOrEmpty(a.customerPhone) &&
                                                a.appointmentIsActive == true
                                                select a;
                    // 2 Dager
                    var reminder2Appointments = from a in db.Appointment
                                                where a.SMSLog.Where(s => s.smsTemplate == SMSTemplate.SMSReminder2.ToString() && s.smsIsSent == true).Count() < 1 &&
                                                a.Start <rm2DateTimeMax &&
                                                         a.Start> rm2DateTimeMin &&
                                                !(a.appointmentCreatedDate <rm2DateTimeMax && a.appointmentCreatedDate> rm2DateTimeMin) &&
                                                !string.IsNullOrEmpty(a.customerId) &&
                                                !string.IsNullOrEmpty(a.customerPhone) &&
                                                a.appointmentIsActive == true
                                                select a;
                    //// 1 Dag
                    //var reminder3Appointments = from a in db.Appointment
                    //                            where a.SMSLog.Where(s => s.smsTemplate == SMSTemplate.SMSReminder3.ToString() && s.smsIsSent == true).Count() < 1
                    //                            && a.Start < rm3DateTimeMax
                    //                            && a.Start > rm3DateTimeMin
                    //                            && !(a.appointmentCreatedDate < rm3DateTimeMax && a.appointmentCreatedDate > rm3DateTimeMin)
                    //                            select a;


                    var surveyAppointments = from a in db.Appointment
                                             where a.SMSLog.Where(s => s.smsTemplate == SMSTemplate.SMSSurvey.ToString() && s.smsIsSent == true).Count() < 1 &&
                                             a.Start < surveyDateTimeMin &&
                                             !string.IsNullOrEmpty(a.customerId) &&
                                             !string.IsNullOrEmpty(a.customerPhone) &&
                                             a.appointmentIsActive == true
                                             select a;

                    List <BookingAppointment> reminder1List = new List <BookingAppointment>();
                    List <BookingAppointment> reminder2List = new List <BookingAppointment>();
                    List <BookingAppointment> surveyList    = new List <BookingAppointment>();
                    //List<BookingAppointment> reminder3List = new List<BookingAppointment>();

                    foreach (var item in reminder1Appointments)
                    {
                        reminder1List.Add(
                            new BookingAppointment {
                            Id              = item.Id
                            , CustomerName  = item.customerName
                            , CustomerPhone = item.customerPhone
                            , ServiceName   = item.serviceName
                            , Start         = new DateTimeTimeZone {
                                DateTime = DateTime.Parse(item.Start.ToString()).ToUniversalTime().ToString("o"), TimeZone = "UTC"
                            }
                            , CustomerEmailAddress = item.customerEmailAddress
                            , End = new DateTimeTimeZone {
                                DateTime = DateTime.Parse(item.End.ToString()).ToUniversalTime().ToString("o"), TimeZone = "UTC"
                            }
                            , Duration        = new TimeSpan(1, 0, 0)
                            , ServiceLocation = new Location {
                                Address       = new PhysicalAddress()
                                , Coordinates = new OutlookGeoCoordinates()
                            }
                        }
                            );
                    }

                    foreach (var item in reminder2Appointments)
                    {
                        reminder2List.Add(
                            new BookingAppointment {
                            Id              = item.Id
                            , CustomerName  = item.customerName
                            , CustomerPhone = item.customerPhone
                            , ServiceName   = item.serviceName
                            , Start         = new DateTimeTimeZone {
                                DateTime = DateTime.Parse(item.Start.ToString()).ToUniversalTime().ToString("o"), TimeZone = "UTC"
                            }
                            , CustomerEmailAddress = item.customerEmailAddress
                            , End = new DateTimeTimeZone {
                                DateTime = DateTime.Parse(item.End.ToString()).ToUniversalTime().ToString("o"), TimeZone = "UTC"
                            }
                            , Duration        = new TimeSpan(1, 0, 0)
                            , ServiceLocation = new Location {
                                Address       = new PhysicalAddress()
                                , Coordinates = new OutlookGeoCoordinates()
                            }
                        }
                            );
                    }

                    foreach (var item in surveyAppointments)
                    {
                        surveyList.Add(
                            new BookingAppointment {
                            Id              = item.Id
                            , CustomerName  = item.customerName
                            , CustomerPhone = item.customerPhone
                            , ServiceName   = item.serviceName
                            , Start         = new DateTimeTimeZone {
                                DateTime = DateTime.Parse(item.Start.ToString()).ToUniversalTime().ToString("o"), TimeZone = "UTC"
                            }
                            , CustomerEmailAddress = item.customerEmailAddress
                            , End = new DateTimeTimeZone {
                                DateTime = DateTime.Parse(item.End.ToString()).ToUniversalTime().ToString("o"), TimeZone = "UTC"
                            }
                            , Duration        = new TimeSpan(1, 0, 0)
                            , ServiceLocation = new Location {
                                Address       = new PhysicalAddress()
                                , Coordinates = new OutlookGeoCoordinates()
                            }
                        }
                            );
                    }

                    //foreach (var item in reminder3Appointments)
                    //{
                    //    reminder3List.Add(
                    //         new BookingAppointment {
                    //             Id = item.Id
                    //            ,CustomerName = item.customerName
                    //            ,CustomerPhone = item.customerPhone
                    //            ,ServiceName = item.serviceName
                    //            ,Start = new DateTimeTimeZone { DateTime =  DateTime.Parse(item.Start.ToString()).ToUniversalTime().ToString("o"), TimeZone = "UTC" }
                    //            ,CustomerEmailAddress = item.customerEmailAddress
                    //            ,End = new DateTimeTimeZone { DateTime = DateTime.Parse(item.End.ToString()).ToUniversalTime().ToString("o"), TimeZone = "UTC" }
                    //            ,Duration = new TimeSpan(1,0,0)
                    //            ,ServiceLocation = new Location {
                    //                 Address = new PhysicalAddress()
                    //                ,Coordinates = new OutlookGeoCoordinates()
                    //            }
                    //        }
                    //    );
                    //}


                    SendSMS(viaNettSMS, _business, reminder1List, SMSTemplate.SMSReminder1);
                    SendSMS(viaNettSMS, _business, reminder2List, SMSTemplate.SMSReminder2);
                    SendSMS(viaNettSMS, _business, surveyList, SMSTemplate.SMSSurvey);
                    //SendSMS(viaNettSMS, _business, reminder3List, SMSTemplate.SMSReminder3);
                }

                System.Threading.Thread.Sleep(60000);
            }
            // End While
        }
        private static void SendSMS(ViaNettSMS viaNettSMS, BookingBusiness _business, IEnumerable <BookingAppointment> _appointments, SMSTemplate sMSTemplate)
        {
            MD5 md5 = MD5.Create();

            foreach (BookingAppointment appointment in _appointments)
            {
                // Send SMS to Customer
                Console.WriteLine("Sending SMS to CustomerName: {0}, CustomerPhone: {1}", appointment.CustomerName, appointment.CustomerPhone);

                ViaNettSMS.Result result;
                string            _appointmentDateString = DateTime.Parse(appointment.Start.DateTime).ToString("dd.MM.yyyy HH:mm");

                string message = RenderSMSTemplate(_business, appointment, _appointmentDateString, sMSTemplate);


                try
                {
                    // Send SMS through HTTP API
                    Console.WriteLine("{0} SendingSMS: {1} {2} {3}", Date.Now.ToString(), _SMSSenderFrom, appointment.CustomerPhone, message);
                    result = viaNettSMS.SendSMS(_SMSSenderFrom, appointment.CustomerPhone, message);
                    //result = viaNettSMS.SendSMS(_SMSSenderFrom, "40453626", message);


                    // Show Send SMS response
                    if (result.Success)
                    {
                        Debug.WriteLine("Message successfully sent");

                        using (BookingEntities context = new BookingEntities())
                        {
                            context.SMSLog.Add(new SMSLog {
                                appointmentId    = appointment.Id
                                , message        = message
                                , recipientPhone = appointment.CustomerPhone
                                , sentDate       = DateTime.Now
                                , smsIsSent      = true
                                , sentResult     = "OK"
                                , smsTemplate    = sMSTemplate.ToString()
                                , md5hash        = md5.ComputeHash(Encoding.Unicode.GetBytes(appointment.Id))
                            });
                            context.SaveChanges();
                        }
                    }
                    else
                    {
                        using (BookingEntities context = new BookingEntities())
                        {
                            context.SMSLog.Add(new SMSLog {
                                appointmentId    = appointment.Id
                                , message        = message
                                , recipientPhone = appointment.CustomerPhone
                                , sentDate       = DateTime.Now
                                , smsIsSent      = false
                                , sentResult     = $"Received error: {result.ErrorCode} {result.ErrorMessage}"
                                , smsTemplate    = sMSTemplate.ToString()
                                , md5hash        = md5.ComputeHash(Encoding.Unicode.GetBytes(appointment.Id))
                            });
                            context.SaveChanges();
                        }
                        Debug.WriteLine($"Received error: {result.ErrorCode} {result.ErrorMessage}");
                    }
                }
                catch (System.Net.WebException ex)
                {
                    //Catch error occurred while connecting to server.
                    Debug.WriteLine(ex.Message);
                }
            }
            md5.Dispose();
        }