context: using CmsData;
  using CmsWeb.Code;
  using iTextSharp.text;
  using iTextSharp.text.pdf;
  using System;
  using System.Linq;
  using System.Text;
  using System.Text.RegularExpressions;
  using System.Web.Mvc;
  using UtilityExtensions;
  
  namespace CmsWeb.Areas.Reports.Models
  {
      public class ContactsResult : ActionResult
      {
          private readonly Font boldfont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 10);
          private readonly int border = Rectangle.NO_BORDER; //PdfPCell.BOX;
          private readonly Font font = FontFactory.GetFont(FontFactory.HELVETICA, 10);
          private readonly Font monofont = FontFactory.GetFont(FontFactory.COURIER, 8);
          private readonly PageEvent pageEvents = new PageEvent();
          private readonly Guid qid;
          private readonly Font smallfont = FontFactory.GetFont(FontFactory.HELVETICA, 8, new GrayColor(50));
          private readonly float[] w = { 40 + 70 + 80, 40 + 130 };
          private readonly float[] w2 = { 40, 70, 80 };
          private readonly float[] w3 = { 40, 130 };
          private PdfContentByte dc;
          private Document doc;
          private DateTime dt;
          private PdfPTable t;
          private bool sortAddress;
          private string OrganizationName;
          private string HeaderText;
          private readonly Font xsmallfont = FontFactory.GetFont(FontFactory.HELVETICA, 7, new GrayColor(50));
  
          public ContactsResult(Guid id, bool? sortAddress, string orgname)
          {
              qid = id;
              this.sortAddress = sortAddress ?? false;
              OrganizationName = orgname;
          }
  
          public override void ExecuteResult(ControllerContext context)
          {
              var Response = context.HttpContext.Response;
  
              dt = Util.Now;
  
              HeaderText = OrganizationName.HasValue()
                  ? $"Contacts - {OrganizationName}: {dt:d}"
                  : $"Contact Report: {dt:d}";
              var filename = HeaderText.SlugifyString("-", false);
              Response.ContentType = "application/pdf";
              Response.AddHeader("content-disposition", $"filename={filename}.pdf");
  
              doc = new Document(PageSize.LETTER.Rotate(), 36, 36, 64, 64);
              var w = PdfWriter.GetInstance(doc, Response.OutputStream);
              w.PageEvent = pageEvents;
              doc.Open();
              dc = w.DirectContent;
              StartPageSet();
              var q = DbUtil.Db.PeopleQuery(qid);
  
              if (sortAddress)
              {
                  q = from p in q
                      orderby p.PrimaryState, p.PrimaryCity, p.PrimaryZip, p.PrimaryCity, p.PrimaryAddress, p.Name2
                      select p;
              }
              else
              {
                  q = from p in q
                      orderby p.Name2
                      select p;
              }
  
              foreach (var p in q)
              {
                  t.AddCell(NewCell(p));
              }
  
              t.SplitLate = false;
              t.SplitRows = true;
              if (t.Rows.Count > 1)
              {
                  doc.Add(t);
              }
              else
              {
                  doc.Add(new Phrase("no data"));
              }
  
              pageEvents.EndPageSet();
              doc.Close();
          }
  
          private void StartPageSet()
          {
              t = new PdfPTable(w);
              t.WidthPercentage = 100;
              t.DefaultCell.Border = border;
              t.DefaultCell.Padding = 5;
              t.HeaderRows = 1;
              pageEvents.StartPageSet(HeaderText);
  
              var t2 = new PdfPTable(w2);
              t2.WidthPercentage = 100;
              t2.DefaultCell.Border = border;
              t2.DefaultCell.Padding = 5;
              t2.AddCell(new Phrase("\nPerson", boldfont));
              t2.AddCell(new Phrase("\nAddress", boldfont));
              t2.AddCell(new Phrase("Phone\nEmail", boldfont));
              var c = new PdfPCell(t.DefaultCell);
              c.AddElement(t2);
              c.Padding = 0;
              t.AddCell(c);
  
              var t3 = new PdfPTable(w3);
              t3.WidthPercentage = 100;
              t3.DefaultCell.Border = border;
              t3.DefaultCell.Padding = 5;
              t3.DefaultCell.PaddingBottom = 0;
              t3.AddCell(new Phrase("\nBirthday", boldfont));
              t3.AddCell(new Phrase("\nMember Status", boldfont));
              c = new PdfPCell(t.DefaultCell);
              c.Padding = 0;
              c.AddElement(t3);
              t.AddCell(c);
          }
  
          private PdfPCell NewCell(Person p)
          {
              if (t.Rows.Count % 2 == 0)
              {
                  t.DefaultCell.BackgroundColor = new GrayColor(240);
              }
              else
              {
                  t.DefaultCell.BackgroundColor = BaseColor.WHITE;
              }
  
              var t2 = new PdfPTable(w2);
              t2.WidthPercentage = 100;
              t2.DefaultCell.Border = border;
              t2.DefaultCell.Padding = 5;
              var name = new Phrase(p.Name + "\n", font);
              name.Add(new Chunk($"  ({p.PeopleId})", smallfont));
              t2.AddCell(name);
              var addr = new StringBuilder(p.PrimaryAddress);
              AddLine(addr, p.PrimaryAddress2);
              AddLine(addr, $"{p.PrimaryCity}, {p.PrimaryState} {p.PrimaryZip.FmtZip()}");
              t2.AddCell(new Phrase(addr.ToString(), font));
              var phones = new StringBuilder();
              AddPhone(phones, p.HomePhone, "h ");
              AddPhone(phones, p.CellPhone, "c ");
              AddPhone(phones, p.WorkPhone, "w ");
              AddLine(phones, p.EmailAddress);
              t2.AddCell(new Phrase(phones.ToString(), font));
              var c = new PdfPCell(t.DefaultCell);
              c.AddElement(GetAttendance(p));
              c.Colspan = 3;
              t2.AddCell(c);
              c = new PdfPCell(t.DefaultCell);
              c.Padding = 0;
              c.AddElement(t2);
              t.AddCell(c);
  
              var t3 = new PdfPTable(w3);
              t3.WidthPercentage = 100;
              t3.DefaultCell.Border = border;
              t3.DefaultCell.Padding = 5;
              t3.DefaultCell.PaddingBottom = 0;
              t3.AddCell(new Phrase(p.DOB, font));
              t3.AddCell(new Phrase(p.MemberStatus.Description));
              var contacts = GetContacts(p);
              if (contacts.Items.Count > 0)
              {
                  c = new PdfPCell(t.DefaultCell);
                  c.Colspan = 2;
                  c.AddElement(new Chunk("Contacts", boldfont));
                  t3.AddCell(c);
                  c = new PdfPCell(t.DefaultCell);
                  c.Colspan = 2;
                  c.AddElement(contacts);
                  t3.AddCell(c);
              }
              c = new PdfPCell(t.DefaultCell);
              c.Padding = 0;
              t3.SplitLate = false;
              t3.SplitRows = true;
              c.AddElement(t3);
              return c;
          }
  
          private void AddLine(StringBuilder sb, string value)
          {
              AddLine(sb, value, string.Empty);
          }
  
          private void AddLine(StringBuilder sb, string value, string postfix)
          {
              if (value.HasValue())
              {
                  if (sb.Length > 0)
                  {
                      sb.Append("\n");
                  }
  
                  sb.Append(value);
                  if (postfix.HasValue())
                  {
                      sb.Append(postfix);
                  }
              }
          }
  
          private void AddPhone(StringBuilder sb, string value, string prefix)
          {
              if (value.HasValue())
              {
                  value = value.FmtFone(prefix);
                  if (sb.Length > 0)
                  {
                      sb.Append("\n");
                  }
  
                  sb.Append(value);
              }
          }
  
          private Paragraph GetAttendance(Person p)
          {
              var q = from a in p.Attends
                      where a.AttendanceFlag
                      orderby a.MeetingDate.Date descending
                      group a by a.MeetingDate.Date
                      into g
                      select g.Key;
              var list = q.ToList();
  
              var attstr = new StringBuilder("\n");
              var dt = Util.Now;
              var yearago = dt.AddYears(-1);
              while (dt > yearago)
              {
                  var dt2 = dt.AddDays(-7);
                  var indicator = ".";
                  foreach (var d in list)
                  {
                      if (d < dt2)
                      {
                          break;
                      }
  
                      if (d <= dt)
                      {
                          indicator = "P";
                          break;
                      }
                  }
                  attstr.Insert(0, indicator);
                  dt = dt2;
              }
  
gt:             var ph = new Paragraph(attstr.ToString(), monofont);