using System;
using System.Collections.Generic;
using System.IO;
using System.Web.Mvc;
using iTextSharp.text.pdf;
using PdfReportingDemo.Models;

namespace PdfReportingDemo.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            // just go straight to the demo
            return RedirectToAction("MyFormLetter");
        }

        public ActionResult About()
        {
            return View();
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult MyFormLetter()
        {
            // by setting the Company property on the model, 
            // the form will be filled out with the company name,
            // but not the applicant name
            Applicant defaultApplicant = new Applicant
                                             {
                                                 Company = "My Company"
                                             };
            return View(defaultApplicant);
        }

        /// <summary>
        /// The MyFormLetter form posts to this action
        /// </summary>
        /// <param name="applicant"></param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult MyFormLetter(Applicant applicant)
        {
            try
            {
                // uncomment this line to test error handling
                throw new NullReferenceException("OH NOOOOOO");

                // this is where you would get further info by calling business logic, data access, etc.
                applicant.Company = "My Company";

                // populate the value of each form field in the pdf form
                Dictionary<string, string> formFields = new Dictionary<string, string>
                                                            {
                                                                {"ApplicantName", applicant.Name},
                                                                {"CompanyName", applicant.Company}
                                                            };
                string fileName = "MyFormLetter.pdf";

                // we don't want the user to see "MyFormLetter.pdf" when they save the file, 
                // we want them to see "YourFormLetter.pdf" when they save the pdf
                // so we alias the name simply by passing it to another action named YourFormLetter

                // pass the file stream result to the alias action
                TempData["MyFormLetter_FileStreamResult"] = GetPdfFileStreamResult(fileName, formFields);
                return RedirectToAction("YourFormLetter");
            }
            catch (Exception ex)
            {
                return HandleErrorForPopup(ex, applicant);
            }
        }

        /// <summary>
        /// When the user saves the pdf, the default name of the file will be "YourFormLetter.pdf".
        /// </summary>
        /// <returns></returns>
        public FileStreamResult YourFormLetter()
        {
            return (FileStreamResult) TempData["MyFormLetter_FileStreamResult"];
        }

        private FileStreamResult GetPdfFileStreamResult(string fileName, Dictionary<string, string> formFields)
        {
            MemoryStream memoryStream = GeneratePdf(fileName, formFields);

            // create a new return stream because the MemoryStream from the file is closed
            MemoryStream returnStream = new MemoryStream();
            returnStream.Write(memoryStream.GetBuffer(), 0, memoryStream.GetBuffer().Length);
            returnStream.Flush();
            // rewind stream back to beginning so it can be rendered to the page
            returnStream.Seek(0, SeekOrigin.Begin);

            return new FileStreamResult(returnStream, "application/pdf");
        }

        private MemoryStream GeneratePdf(string fileName, Dictionary<string, string> formFields)
        {
            string formFile = HttpContext.Server.MapPath("~/Forms/" + fileName);
            PdfReader reader = new PdfReader(formFile);
            MemoryStream memoryStream = new MemoryStream();
            PdfStamper stamper = new PdfStamper(reader, memoryStream);
            AcroFields fields = stamper.AcroFields;

            // set form fields
            foreach (KeyValuePair<string, string> formField in formFields)
            {
                fields.SetField(formField.Key, formField.Value);
            }

            stamper.FormFlattening = true;
            // release file
            stamper.Close();
            reader.Close();

            return memoryStream;
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult HandleErrorForPopup(Exception ex, object inputData)
        {
            //TODO: log and/or email error


            // close the popup browser window and display the error in the parent window
            TempData["ErrorMessage"] = ex.Message;
            return RedirectToAction("ParentError");
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult ParentError()
        {
            return View();
        }
    }
}