using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Web.Http;
using Newtonsoft.Json.Linq;
using WebMail.Model;
using Telerik.Web.UI;
using Telerik.Windows.Documents.Flow.FormatProviders.Docx;
using Telerik.Windows.Documents.Flow.Model;
using Telerik.Windows.Documents.Flow.Model.Editing;
using Telerik.Windows.Documents.Flow.Model.Styles;
using Telerik.Windows.Documents.Spreadsheet.FormatProviders;
using Telerik.Windows.Documents.Spreadsheet.FormatProviders.OpenXml.Xlsx;
using Telerik.Windows.Documents.Spreadsheet.Model;

public class ContactsController : ApiController
{
    private WebMailContext db = new WebMailContext();

    [HttpGet]
    [Route("api/contacts")]
    public IEnumerable<Contact> Get()
    {
        var contacts = from contact in db.Contacts
                       select contact;

        return contacts;
    }

    public Contact Get(string id)
    {
        Contact contact = db.Contacts.FirstOrDefault(c => c.Id == id);

        if (contact == null)
        {
            var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
            {
                Content = new StringContent(string.Format("No contat with ID = {0}", id)),
                ReasonPhrase = "Contact ID Not Found"
            };
            throw new HttpResponseException(resp);
        }
        return contact;
    }

    [HttpPost]
    [Route("api/contacts")]
    public HttpResponseMessage Post([FromBody]Contact contact)
    {
        db.Contacts.Add(contact);
        db.SaveChanges();

        return Request.CreateResponse<Contact>(HttpStatusCode.Created, contact);
    }

    public HttpResponseMessage Put(string id, [FromBody]Contact updatedContact)
    {
        var contact = db.Contacts.FirstOrDefault(x => x.Id == id);

        if (contact != null)
        {
            contact.Name = updatedContact.Name;
            contact.Company = updatedContact.Company;
            contact.Email = updatedContact.Email;
            contact.Country = updatedContact.Country;
            contact.City = updatedContact.City;
            contact.Phone = updatedContact.Phone;

            db.SaveChanges();
        }

        return Request.CreateResponse<Contact>(HttpStatusCode.NoContent, contact);
    }

    public HttpResponseMessage Delete(string id)
    {
        var contact = db.Contacts.SingleOrDefault(x => x.Id == id);

        if (contact != null)
        {
            db.Contacts.Remove(contact);
            db.SaveChanges();
            return new HttpResponseMessage(HttpStatusCode.OK);
        }

        return new HttpResponseMessage(HttpStatusCode.NotFound);
    }

    [HttpPost]
    [Route("api/contacts/search")]
    public SearchBoxData Search([FromBody]JObject context)
    {
        string text = (string)context["context"]["Text"];
        IEnumerable<SearchBoxItemData> filtered = from contact in db.Contacts
                                                  where contact.Name.StartsWith(text)
                                                  select new SearchBoxItemData
                                                  {
                                                      Text = contact.Name,
                                                      Value = contact.Id
                                                  };

        SearchBoxData res = new SearchBoxData();
        res.Items = filtered.ToArray();

        return res;

    }

    [HttpGet]
    [Route("api/contacts/xlsx")]
    public HttpResponseMessage Xlsx()
    {
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
        response.Content = new ByteArrayContent(ExportToXlsx());

        response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.Content.Headers.ContentDisposition.FileName = "Contacts.xlsx";

        return response;
    }

    [HttpGet]
    [Route("api/contacts/csv")]
    public HttpResponseMessage Csv()
    {
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
        response.Content = new ByteArrayContent(ExportToCsv());

        response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
        response.Content.Headers.ContentDisposition.FileName = "Contacts.csv";
        
        return response;
    }

    [HttpGet]
    [Route("api/contacts/docx")]
    public HttpResponseMessage Docx()
    {
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);

        response.Content = new ByteArrayContent(ExportToDocx());        
        response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.Content.Headers.ContentDisposition.FileName = "Contacts.docx";
        
        return response;
    }

    public byte[] ExportToXlsx()
    {
        Workbook workbook = new Workbook();
        Worksheet worksheet = workbook.Worksheets.Add();
        worksheet.Name = "Contacts";

        var contacts = db.Contacts.ToList();

        worksheet.Cells[0, 0].SetValue("Id");
        worksheet.Cells[0, 1].SetValue("Name");
        worksheet.Cells[0, 2].SetValue("Title");
        worksheet.Cells[0, 3].SetValue("Country");
        worksheet.Cells[0, 4].SetValue("City");
        worksheet.Cells[0, 5].SetValue("Company");
        worksheet.Cells[0, 6].SetValue("Phone");
        worksheet.Cells[0, 7].SetValue("Email");

        int i = 1;

        foreach (Contact contact in contacts)
        {
            worksheet.Cells[i, 0].SetValue(contact.Id);
            worksheet.Cells[i, 1].SetValue(contact.Name);
            worksheet.Cells[i, 2].SetValue(contact.Title);
            worksheet.Cells[i, 3].SetValue(contact.Country);
            worksheet.Cells[i, 4].SetValue(contact.City);
            worksheet.Cells[i, 5].SetValue(contact.Company);
            worksheet.Cells[i, 6].SetValue(contact.Phone);
            worksheet.Cells[i, 7].SetValue(contact.Email);

            i++;
        }

        worksheet.Columns[worksheet.UsedCellRange].AutoFitWidth();

        using (MemoryStream output = new MemoryStream())
        {
            IWorkbookFormatProvider formatProvider = new XlsxFormatProvider();
            formatProvider.Export(workbook, output);

            return output.ToArray();
        }
    }

    public byte[] ExportToCsv()
    {
        var contacts = db.Contacts.ToList();

        using (MemoryStream stream = new MemoryStream())
        {
            using (var csvWriter = new StreamWriter(stream, Encoding.UTF8))
            {
                csvWriter.WriteLine("Id,Name,Title,Country,City,Company,Phone,Email\r\n");

                foreach (Contact contact in contacts)
                {
                    csvWriter.WriteLine(string.Format("{0},{1},{2},{3},{4},{5},{6},{7}", contact.Id, contact.Name, contact.Title, contact.Country, contact.City, contact.Company, contact.Phone, contact.Email));
                }

                csvWriter.Flush();
            }

            return stream.ToArray();
        }
    }

    public byte[] ExportToDocx()
    {
        var contacts = db.Contacts.ToList();

        RadFlowDocument document = new RadFlowDocument();

        document.Sections.AddSection();
        document.HasDifferentEvenOddPageHeadersFooters = true;

        Header defaultHeader = document.Sections.First().Headers.Add();
        Paragraph defaultHeaderParagraph = defaultHeader.Blocks.AddParagraph();
        defaultHeaderParagraph.TextAlignment = Alignment.Right;
        defaultHeaderParagraph.Inlines.AddRun("Contacts Word Export");

        RadFlowDocumentEditor editor = new RadFlowDocumentEditor(document);

        foreach (Contact contact in contacts)
        {
            editor.InsertLine(string.Format("{0},{1}", contact.Name, contact.Email));
        }

        DocxFormatProvider provider = new DocxFormatProvider();

        using (MemoryStream output = new MemoryStream())
        {
            provider.Export(document, output);

            return output.ToArray();
        }
    }
}
