public static void SendMixmagOnlineEmail(string[] args)
		{
			DateTime issueDate = new DateTime(2011, 7, 1);
			int? coverId = null;

			Console.WriteLine("============");
			Console.WriteLine("SendMixmagOnlineEmail {0}, coverId={1}", issueDate.ToString("MMM").ToUpper(), coverId.HasValue ? coverId.Value.ToString() : "none");
			Console.WriteLine("============");


			if (args.Length == 0)
			{
				Console.WriteLine("Press any key...");
				Console.ReadLine();
			}

			MixmagIssue currentIssue = MixmagIssue.GetIssueFromDate(issueDate, coverId);
			if (currentIssue == null)
				throw new Exception("No issue for this date");
			if (!(currentIssue.Ready.HasValue && currentIssue.Ready.Value))
				throw new Exception("This issue is not ready yet!");

			Query qBackIssues = new Query();
			qBackIssues.OrderBy = new OrderBy(MixmagIssue.Columns.IssueCoverDate, OrderBy.OrderDirection.Descending);
			qBackIssues.QueryCondition = new And(
				new Q(MixmagIssue.Columns.K, QueryOperator.NotEqualTo, currentIssue.K),
				new Q(MixmagIssue.Columns.Ready, true));
			qBackIssues.TopRecords = 3;
			MixmagIssueSet backIssues = new MixmagIssueSet(qBackIssues);

			StringBuilder sb = new StringBuilder();

			//sb.Append("<p>This is a paragraph of HTML that we can edit for each issue.</p>");

			sb.Append("<h1>Latest Mixmag issue:</h1>");
			sb.Append(currentIssue.GetHtml(null, true));
			sb.Append("<div style=\"height:1px width:1px; clear: both; color:#ffffff;\">.</div>");

			if (backIssues.Count > 0)
			{
				sb.Append("<h1>Recent Mixmag issues:</h1>");
				foreach (MixmagIssue backIssue in backIssues)
					sb.Append(backIssue.GetHtml(null, true));
				sb.Append("<div style=\"height:1px width:1px; clear: both; color:#ffffff;\">.</div>");
			}
			string html = sb.ToString();



			Console.WriteLine("Selecting...", 1);
			Query q = new Query();
			q.QueryCondition = new And(
				new Q(MixmagSubscription.Columns.FacebookPermissionEmail, true),
				new Q(MixmagSubscription.Columns.SendMixmag, true),
				Vars.DevEnv ? new Q(MixmagSubscription.Columns.FacebookUID, 513584417) : new Q(true)
			);
			MixmagSubscriptionSet bs = new MixmagSubscriptionSet(q);
			Console.WriteLine("Found " + bs.Count.ToString("#,##0") + " item(s)...", 1);
			List<string> emails = new List<string>();
			System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient();
			client.Host = Common.Properties.GetDefaultSmtpServer();
			for (int count = 0; count < bs.Count; count++)
			{
				MixmagSubscription c = bs[count];

				try
				{
					try
					{
						Console.Write("incrementing counter for uid={0}...", c.FacebookUID.ToString());
						Facebook.FacebookResponse<string> response = Facebook.Desktop.FacebookDesktopContext.Current(Facebook.Apps.MixmagOnline).Dashboard.IncrementCount(c.FacebookUID.ToString());
						Console.WriteLine("done! response={0}.", response.Value);

					}
					catch(Exception ex)
					{
						Console.WriteLine("exception: {0}", ex.ToString());
					}


					string subject = "Mixmag " + currentIssue.IssueCoverDate.Value.ToString("MMMM yyyy") + " - " + currentIssue.Contents[0].Tagline;
					if (c.IsEmailComplete.HasValue && c.IsEmailComplete.Value && c.IsEmailVerified.HasValue && c.IsEmailVerified.Value && !(c.IsEmailBroken.HasValue && c.IsEmailBroken.Value) && !emails.Contains(c.Email))
					{
						//send email

						System.Net.Mail.MailMessage m = new System.Net.Mail.MailMessage();
						m.Subject = subject;
						m.Body = html + "<p>To unsubscribe click here: <a href=\"http://www.mixmag-online.com/?k=" + c.K + "&email=" + c.Email + "\">http://www.mixmag-online.com/?k=" + c.K + "&email=" + c.Email + "</a></p>";
						m.From = new System.Net.Mail.MailAddress("*****@*****.**", "Mixmag");
						m.ReplyTo = new System.Net.Mail.MailAddress("*****@*****.**", "Mixmag");
						if (Vars.DevEnv)
							m.To.Add("*****@*****.**");
						else
							m.To.Add(c.Email);

						m.IsBodyHtml = true;

						Console.WriteLine("Sending email to " + c.Email);

						client.Send(m);
						

						emails.Add(c.Email);
					}
					else
					{
						//send email via facebook
						Facebook.Desktop.FacebookDesktopContext.Current(Facebook.Apps.MixmagOnline).Notifications.SendEmail(
							new string[] { c.FacebookUID.ToString() },
							subject,
							"",
							html + "<p>To unsubscribe click here: <a href=\"http://www.mixmag-online.com/?k=" + c.K + "&uid=" + c.FacebookUID.ToString() + "\">http://www.mixmag-online.com/?k=" + c.K + "&uid=" + c.FacebookUID.ToString() + "</a></p>");


						//Dashboard.incrementCount

						Console.WriteLine("Sending via facebook to " + c.FacebookUID);
					}
					// Do work here!
					c.TotalSent++;
					c.Update();

					currentIssue.TotalSent++;
					currentIssue.Update();


					if (count % 10 == 0)
						Console.WriteLine("Done " + count + "/" + bs.Count, 2);

				}
				catch (Exception ex)
				{
					Console.WriteLine("Exception " + count + "/" + bs.Count + " - " + ex.ToString(), 3);
				}

				bs.Kill(count);

			}
			Console.WriteLine("All done!");
			Console.ReadLine();
		}
		protected void Page_Load(object sender, EventArgs e)
		{

			Query qAll = new Query();
			qAll.Columns = new ColumnSet(Country.Columns.FriendlyName, Country.Columns.K);
			qAll.OrderBy = new OrderBy(Country.Columns.FriendlyName);
			qAll.QueryCondition = new Q(Country.Columns.Enabled, true);
			CountrySet csAll = new CountrySet(qAll);

			CountryDropDownList.DataSource = csAll;
			CountryDropDownList.DataTextField = "FriendlyName";
			CountryDropDownList.DataValueField = "K";
			CountryDropDownList.DataBind();

			CountryDropDownList.SelectedValue = IpCountry.ClientCountryK().ToString();


			if (Request.QueryString["k"] != null && Request.QueryString["code"] != null)
			{
				Bobs.MixmagSubscription ms = new Bobs.MixmagSubscription(int.Parse(Request.QueryString["k"]));
				if (ms.EmailVerificationSecret.ToLower() == Request.QueryString["code"].ToLower())
				{
					ms.IsEmailVerified = true;
					ms.Update();
				}
			}

			if (Request.QueryString["k"] != null && Request.QueryString["email"] != null)
			{
				Bobs.MixmagSubscription ms = new Bobs.MixmagSubscription(int.Parse(Request.QueryString["k"]));
				if (ms.Email.ToLower() == Request.QueryString["email"].ToLower())
				{
					Query q = new Query();
					q.QueryCondition = new Q(Bobs.MixmagSubscription.Columns.Email, ms.Email);
					MixmagSubscriptionSet mss = new MixmagSubscriptionSet(q);
					foreach (Bobs.MixmagSubscription ms1 in mss)
					{
						ms1.SendMixmag = false;
						ms1.Update();
					}
				}
			}

			if (Request.QueryString["k"] != null && Request.QueryString["uid"] != null)
			{
				Bobs.MixmagSubscription ms = new Bobs.MixmagSubscription(int.Parse(Request.QueryString["k"]));
				if (ms.FacebookUID == int.Parse(Request.QueryString["uid"]))
				{
					ms.SendMixmag = false;
					ms.Update();
				}
			}

			if (IssueDate.HasValue)
			{
				string code = IssueDate.Value.Year.ToString("0000");
				code += IssueDate.Value.Month.ToString("00");
				code += CoverId.HasValue ? CoverId.Value.ToString("0") : "0";
				if (PageNumber.HasValue && PageNumber.Value > 0)
				{
					code += PageNumber.Value.ToString();
				}
				RequestCode.Value = code;
			}


			int selectedIssue = 0;
			DateTime? selectedIssueDate = null;
			if (IssueDate.HasValue)
			{
				DateTime month = IssueDate.Value;
				Query q = new Query();
				if (CoverId.HasValue)
				{
					q.QueryCondition = new And(
						new Q(MixmagIssue.Columns.IssueCoverDate, month),
						new Q(MixmagIssue.Columns.IssueCoverId, CoverId.Value)
					);
				}
				else
				{
					q.QueryCondition = new Q(MixmagIssue.Columns.IssueCoverDate, month);
				}
				q.OrderBy = new OrderBy(MixmagIssue.Columns.IssueCoverId);
				MixmagIssueSet mis = new MixmagIssueSet(q);
				if (mis.Count > 0)
				{
					MixmagIssue issue = mis[0];

					LoginButtonIntroTextP.InnerText = "You must connect with Facebook to read Mixmag:";

					FacebookHttpContext context = null;
					try
					{
						context = FacebookHttpContext.Current;
					}
					catch { }

					if (context != null)
					{
						var usrR = FacebookHttpContext.Current.Users.GetLoggedInUser();
						if (usrR != null && usrR.Value > 0)
						{
							Query q2 = new Query();
							q2.QueryCondition = new Q(Bobs.MixmagSubscription.Columns.FacebookUID, usrR.Value);
							MixmagSubscriptionSet mss = new MixmagSubscriptionSet(q2);
							if (mss.Count > 0)
							{
								Bobs.MixmagSubscription subscriber = mss[0];

								MixmagRead mr = null;
								try
								{
									mr = new MixmagRead(subscriber.K, issue.K);
								}
								catch (BobNotFound)
								{
									mr = new MixmagRead();
									mr.MixmagSubscriberK = subscriber.K;
									mr.MixmagIssueK = issue.K;
									mr.DateTimeRead = DateTime.Now;
								}
								if (subscriber.PublishStoryOnRead.HasValue && subscriber.PublishStoryOnRead.Value)
								{
									//Have we sent a message to this subscribers facebook wall on the last 12 hours? If so, don't send this one.
									Query q3 = new Query();
									q3.QueryCondition = new And(
										new Q(MixmagRead.Columns.MixmagSubscriberK, subscriber.K),
										new Q(MixmagRead.Columns.DateTimeLastStoryPublished, QueryOperator.GreaterThan, DateTime.Now.AddHours(-48)),
										new Q(MixmagRead.Columns.StoryPublished, true)
									);
									MixmagReadSet mrs = new MixmagReadSet(q3);
									if (mrs.Count == 0)
									{
										//send to wall...
										bool found = false;
										if (PageNumber.HasValue)
										{
											foreach (MixmagIssue.ContentsItem item in issue.Contents)
											{
												if (item.PageNumber == PageNumber.Value)
												{
													FacebookHttpContext.Current.Status.Set(item.StatusMessage + " - " + issue.Url(true, PageNumber));
													found = true;
												}
											}
										}
										if (!found)
											FacebookHttpContext.Current.Status.Set(issue.Contents[0].StatusMessage + " - " + issue.Url(true, null));
									

										mr.StoryPublished = true;
										mr.DateTimeLastStoryPublished = DateTime.Now;
										
									}
								}
								
								if (mr.TotalReads.HasValue)
									mr.TotalReads++;
								else
									mr.TotalReads = 1;

								mr.DateTimeLastRead = DateTime.Now;
								mr.Update();

								if (issue.TotalRead.HasValue)
									issue.TotalRead++;
								else
									issue.TotalRead = 1;

								issue.Update();
								//Response.Redirect(issue.CerosUrl);
								Response.Write(@"<FRAMESET cols=""100%""><FRAMESET rows=""100%""><FRAME src=""" + issue.CerosUrl + (PageNumber.HasValue ? ("/page/" + PageNumber.ToString()) : "") + @"""></FRAMESET></FRAMESET>");
								Response.End();

							}
						}
					}

					SelectedIssueHolder.Visible = true;
					SelectedIssuePh.Controls.Clear();
					SelectedIssuePh.Controls.Add(new LiteralControl(issue.GetHtml(PageNumber, false)));
					selectedIssue = issue.K;
				}
			}

			if (selectedIssue == 0)
			{
				//Get latest issue
				Query q1 = new Query();
				q1.QueryCondition = new And(
					new Q(MixmagIssue.Columns.DateTimeSend, QueryOperator.LessThan, DateTime.Now),
					new Q(MixmagIssue.Columns.Ready, true));
				q1.OrderBy = new OrderBy(MixmagIssue.Columns.IssueCoverDate, OrderBy.OrderDirection.Descending);
				q1.TopRecords = 1;
				MixmagIssueSet latestDateTimeSet = new MixmagIssueSet(q1);

				if (latestDateTimeSet.Count > 0)
				{
					selectedIssueDate = latestDateTimeSet[0].IssueCoverDate;

					Query q2 = new Query();
					q2.QueryCondition = new And(
						new Q(MixmagIssue.Columns.DateTimeSend, QueryOperator.LessThan, DateTime.Now),
						new Q(MixmagIssue.Columns.Ready, true),
						new Q(MixmagIssue.Columns.IssueCoverDate, latestDateTimeSet[0].IssueCoverDate.Value));
					q2.OrderBy = new OrderBy(MixmagIssue.Columns.IssueCoverId);

					MixmagIssueSet latestIssueSet = new MixmagIssueSet(q2);
					if (latestIssueSet.Count > 0)
					{
						SelectedIssueHeader.InnerHtml = "Current issue" + (latestIssueSet.Count > 1 ? "s" : "");
						SelectedIssuePh.Controls.Clear();
						foreach (MixmagIssue issue in latestIssueSet)
							SelectedIssuePh.Controls.Add(new LiteralControl(issue.GetHtml(null, false)));
						SelectedIssueHolder.Visible = true;
						
					}
				}
			}



			{
				Query q = new Query();
				q.QueryCondition = new And(
					new Q(MixmagIssue.Columns.DateTimeSend, QueryOperator.LessThan, DateTime.Now),
					new Q(MixmagIssue.Columns.Ready, true),
					selectedIssue > 0 ? new Q(MixmagIssue.Columns.K, QueryOperator.NotEqualTo, selectedIssue) : new Q(true),
					selectedIssueDate.HasValue ? new Q(MixmagIssue.Columns.IssueCoverDate, QueryOperator.NotEqualTo, selectedIssueDate) : new Q(true));
				q.OrderBy = new OrderBy(
					new OrderBy(MixmagIssue.Columns.IssueCoverDate, OrderBy.OrderDirection.Descending),
					new OrderBy(MixmagIssue.Columns.IssueCoverId));
				q.TopRecords = 24;
				MixmagIssueSet backIssues = new MixmagIssueSet(q);
				if (backIssues.Count > 0)
				{
					StringBuilder sb = new StringBuilder();
					foreach (MixmagIssue mi in backIssues)
					{
						sb.Append(mi.GetHtml(null, false));
					}
					BackIssuesPh.Controls.Clear();
					BackIssuesPh.Controls.Add(new LiteralControl(sb.ToString()));
					BackIssuesHolder.Visible = true;
				}
			}



		}
		public static MixmagIssue GetIssueFromDate(DateTime d, int? coverId)
		{
			Query q = new Query();
			if (coverId.HasValue && coverId.Value > 0)
				q.QueryCondition = new And(new Q(MixmagIssue.Columns.IssueCoverDate, d), new Q(MixmagIssue.Columns.IssueCoverId, coverId.Value));
			else
				q.QueryCondition = new Q(MixmagIssue.Columns.IssueCoverDate, d);
			MixmagIssueSet ms = new MixmagIssueSet(q);
			if (ms.Count > 0)
				return ms[0];
			else
				return null;
		}