using System;
using System.Diagnostics;
//using Microsoft.Office.Interop.Word;
//using Aspose.Words;
using System.Linq;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;
using System.Globalization;
using Microsoft.Xrm.Client;
using System.IO;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm;
using System.Drawing;
using Aspose.Words;
using Aspose.Words.Drawing;
using Aspose.Words.Tables;
//using Spire.Doc;
//using Spire.Doc.Documents;
//using Spire.Doc.Fields;
//using Spire.Doc.Collections;
//using Microsoft.Xrm.Sdk.Query;
namespace AnnotationFileRename
{
    public class FileRenamePlugin : IPlugin
    {
        private Guid _annotationId;
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService debug = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            Entity annotationEntity = null;
            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
            {
                // Obtain the target business entity from the input parmameters.
                annotationEntity = (Entity)context.InputParameters["Target"];
                //TODO Test for an entity type and message supported by your plug-in.
                if (context.PrimaryEntityName != "annotation") { return; }
                if (context.MessageName.ToLower() != "create") { return; }
                try
                {
                    String regardingObjType = annotationEntity["objecttypecode"].ToString();
                    //check if the regarding object name is of the entity that you are attaching the files
                    if (regardingObjType.ToLower() == "new_resources")
                    {
                        IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                        IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
                        /*-----------------------------------*/
                        Entity entity = new Entity("new_resources");
                        // An accountnumber attribute should not already exist because
                        // it is system generated. 
                        debug.Trace("noerror:{0}", entity.LogicalName);
                        if (entity.Attributes.Contains("new_myfield") == false)
                        {
                            //IOrganizationService service = factory.CreateOrganizationService(context.UserId);
                            OrganizationServiceContext orgContext = new OrganizationServiceContext(service);
                            if (entity.Attributes.Contains("new_lookup") == true)
                            {
                                var ttGuid = ((EntityReference)entity["new_lookup"]).Id;
                                //Grab case to create subcase on
                                var subTT = (from CN in orgContext.CreateQuery()
                                             where CN.Id == ttGuid
                                             select CN).First();
                                //Check for existing sub TT numbers
                                var checkForCounter = from entry in orgContext.CreateQuery()
                                                      where entry.new_name == subTT.new_myfield
                                                      select entry;
                                int i = 0;
                                foreach (var t in checkForCounter)
                                {
                                    i++;
                                }
                                //if sub tt doesnt exist, create counter for sub tt
                                if (i == 0)
                                {
                                    var counter = new new_dummy();
                                    {
                                        new_name = subTT.new_myfield;
                                        new_counter = 0;
                                    }
                                    orgContext.AddObject(counter);
                                    orgContext.SaveChanges();
                                }
                                //read from sub tt and tt number and set this number as TTNUBMER - SUBTTNUMBER on the form. save changes
                                var subCounter = checkForCounter.First();
                                var sub = subCounter.new_counter + 1;
                                var main = subTT.new_myfield;
                                entity.Attributes.Add("new_myfield", main + "-" + sub.ToString());
                                subCounter.new_counter = sub;
                                orgContext.UpdateObject(subCounter);
                                orgContext.SaveChanges();
                            }
                            else
                            {
                                //if no sub tt has been selected create new, grab counter from CaseCounter entry and add 1, save after this
                                var query = from CN in orgContext.CreateQuery()
                                            where CN.new_name == "CaseCounter"
                                            select CN;
                                String combinedFileName = null;
                                EntityReference regardingObject = (EntityReference)annotationEntity["objectid"];
                                Guid regardingObjGuid = regardingObject.Id;
                                _annotationId = regardingObjGuid;
                                foreach (var entry in query)
                                {
                                    var t = entry.new_counter + 1;
                                    string patientid;
                                    if (t < 10)
                                    {
                                        patientid = "RX-000000" + t.ToString();
                                    }
                                    else if (t < 100)
                                    {
                                        patientid = "RX-00000" + t.ToString();
                                    }
                                    else if (t < 1000)
                                    {
                                        patientid = "RX-0000" + t.ToString();
                                    }
                                    else if (t < 10000)
                                    {
                                        patientid = "RX-000" + t.ToString();
                                    }
                                    else if (t < 100000)
                                    {
                                        patientid = "RX-00" + t.ToString();
                                    }
                                    else if (t < 1000000)
                                    {
                                        patientid = "RX-0" + t.ToString();
                                    }
                                    else
                                    {
                                        patientid = "RX-" + t.ToString();
                                    }
                                    //entity.Attributes.Add("new_myfield", patientid);
                                    string abc = patientid;
                                    entry.new_counter = t;
                                    orgContext.UpdateObject(entry);
                                    orgContext.SaveChanges();
                                    /*-------------------------------------*/
                                    //Get the guid of the regarding object
                                    //EntityReference regardingObject = (EntityReference)annotationEntity["objectid"];
                                    //Guid regardingObjGuid = regardingObject.Id;
                                    //retrieve the required details from the regarding object
                                    Entity resdexEntity = service.Retrieve("new_resources", regardingObjGuid, new ColumnSet("new_name", "new_currentcompany", "new_keyskills", "new_totalexperienceyrs"));
                                    //I am assuming all the columns are string except yearsofexperience
                                    String nameofcand = resdexEntity["new_name"].ToString();
                                    String nameofcompany = resdexEntity["new_currentcompany"].ToString();
                                    string keyskills = resdexEntity.FormattedValues["new_keyskills"].ToString();
                                    //String keyskills = resdexEntity["new_keyskills"].ToString();
                                    String yearofexperience = resdexEntity["new_totalexperienceyrs"].ToString();
                                    DateTime currentDate = new DateTime();
                                    currentDate = DateTime.Now;
                                    DateTimeFormatInfo fmt = (new CultureInfo("hr-HR")).DateTimeFormat;
                                    // currentDate.Date will give the date part only from a datetime object
                                    // The format of date is changed to be like 15.3.2008
                                    String dateInString = currentDate.Date.ToString("d", fmt);
                                    string a = dateInString;
                                    string b = string.Empty;
                                    int val = 0;
                                    for (int i = 0; i < a.Length; i++)
                                    {
                                        if (Char.IsDigit(a[i]))
                                            b += a[i];
                                    }
                                    if (b.Length > 0)
                                        val = int.Parse(b);
                                    //dateInString.ToString()
                                    String xyz = annotationEntity["filename"].ToString();
                                    //xyz.Substring(".doc");
                                    //  xyz.IndexOf(".");
                                    String extension;
                                    extension = Path.GetExtension(xyz);
                                    Console.WriteLine("GetExtension('{0}') returns '{1}'",
                                        xyz, extension);
                                    //String combinedFileName = null;
                                    if (extension == ".docx")
                                    {
                                        combinedFileName = " Napstr" + abc + "_" + nameofcand + "_" + nameofcompany + "_" + keyskills + "_" + yearofexperience + "_" + val + extension;
                                    }
                                    if (extension == ".doc")
                                    {
                                        combinedFileName = " Napstr" + abc + "_" + nameofcand + "_" + nameofcompany + "_" + keyskills + "_" + yearofexperience + "_" + val + extension;
                                    }
                                    if (extension == ".pdf")
                                    {
                                        combinedFileName = " Napstr" + abc + "_" + nameofcand + "_" + nameofcompany + "_" + keyskills + "_" + yearofexperience + "_" + val + extension;
                                    }
                                    if (extension == ".Rtf")
                                    {
                                        combinedFileName = " Napstr" + abc + "_" + nameofcand + "_" + nameofcompany + "_" + keyskills + "_" + yearofexperience + "_" + val + extension;
                                    }
                                    annotationEntity["filename"] = combinedFileName;
                                    //Put the modified annotation entity object into the inputparameters property bag
                                    context.InputParameters.Add("filename", combinedFileName);
                                    byte[] imageBytes = Convert.FromBase64String(annotationEntity["documentbody"].ToString());
                                    MemoryStream docStream = new MemoryStream(imageBytes, 0, imageBytes.Length);
                                    MemoryStream dcs = new MemoryStream();
                                    docStream.CopyTo(dcs);
                                    Document doc = new Document(dcs);
                                    DocumentBuilder builder = new DocumentBuilder(doc);
                                    InsertWatermarkText(doc, "NapstrIT");
                                    //doc.Save("D:\\New folder\\" + "TestFile Out.doc");
                                    MemoryStream outStream = new MemoryStream();
                                    // Save the document to stream.
                                    doc.Save(outStream, SaveFormat.Docx);
                                    byte[] docBytes = outStream.ToArray();
                                    annotationEntity["documentbody"] = Convert.ToBase64String(docBytes);
                                    context.InputParameters.Add("documentbody", Convert.ToBase64String(docBytes));
                                }
                                //Document document = new Document();
                                //document.LoadFromStream(docStream, FileFormat.Docx);
                                ////Create section
                                //Section section = document.AddSection();
                                //HeaderFooter header = section.HeadersFooters.Header;
                                //Paragraph headerParagraph = header.AddParagraph();
                                //DocPicture headerPicture = headerParagraph.AppendPicture(Image.FromFile("C:\\Program Files\\Microsoft Dynamics CRM\\Server\\bin\\assembly\\Header.jpg"));
                                ////Picture layout
                                //headerPicture.TextWrappingStyle = TextWrappingStyle.Behind;
                                //headerPicture.HorizontalOrigin = HorizontalOrigin.Page;
                                //headerPicture.HorizontalAlignment = ShapeHorizontalAlignment.Center;
                                //headerPicture.VerticalOrigin = VerticalOrigin.Page;
                                //headerPicture.VerticalAlignment = ShapeVerticalAlignment.Top;
                                //document.SaveToStream(dcs, FileFormat.Docx);
                            }
                        }
                    }
                }
                catch (FaultException ex)
                {
                    debug.Trace("Errata:\t{0}\nMessage:\t{1}\nAction:\t{2}\nCode:\t{3}\n", ex.Source, ex.Message, ex.Action, ex.Code.ToString());
                    debug.Trace("Org Fault Desc\nDetail Message:\t{0}\nError Details:\t{1}\nError Code:\t{2}\n", ex.Detail.Message, ex.Detail.ErrorDetails.ToString(), ex.Detail.ErrorCode.ToString());
                    throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
                }
            }
        }
        private static void InsertWatermarkText(Document doc, string watermarkText)
        {
            // Create a watermark shape. This will be a WordArt shape. 
            // You are free to try other shape types as watermarks.
            //Shape watermark = new Shape(doc, ShapeType.Image);
            // Set up the text of the watermark.
            Shape watermark = new Shape(doc, ShapeType.Image);
            watermark.ImageData.SetImage("C:\\Program Files\\Microsoft Dynamics CRM\\Server\\bin\\assembly\\Header.jpg");
            //watermark.ImageData = "D:\\NewFolder\\school.jpg";
            watermark.TextPath.FontFamily = "Arial";
            watermark.Width = 500;
            watermark.Height = 99;
            // Text will be directed from the bottom-left to the top-right corner.
            //watermark.Rotation = -40;
            // Remove the following two lines if you need a solid black text.
            watermark.Fill.Color = Color.Gray; // Try LightGray to get more Word-style watermark
            watermark.StrokeColor = Color.Gray; // Try LightGray to get more Word-style watermark
            watermark.BehindText = true;
            // Place the watermark in the page center.
            watermark.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
            watermark.RelativeVerticalPosition = RelativeVerticalPosition.Page;
            watermark.WrapType = WrapType.None;
            watermark.VerticalAlignment = VerticalAlignment.Top;
            watermark.HorizontalAlignment = HorizontalAlignment.Center;
            // Create a new paragraph and append the watermark to this paragraph.
            Paragraph watermarkPara = new Paragraph(doc);
            watermarkPara.AppendChild(watermark);
            // Insert the watermark into all headers of each document section.
            foreach (Section sect in doc.Sections)
            {
                // There could be up to three different headers in each section, since we want
                // the watermark to appear on all pages, insert into all headers.
                InsertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HeaderPrimary);
                InsertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HeaderFirst);
                InsertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HeaderEven);
            }
        }
        private static void InsertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, HeaderFooterType headerType)
        {
            HeaderFooter header = sect.HeadersFooters[headerType];
            if (header == null)
            {
                // There is no header of the specified type in the current section, create it.
                header = new HeaderFooter(sect.Document, headerType);
                sect.HeadersFooters.Add(header);
            }
            // Insert a clone of the watermark into the header.
            header.AppendChild(watermarkPara.Clone(true));
        }
        private static void CopyHeadersFootersFromPreviousSection(Section section)
        {
            Section previousSection = (Section)section.PreviousSibling;
            if (previousSection == null)
                return;
            section.HeadersFooters.Clear();
            foreach (HeaderFooter headerFooter in previousSection.HeadersFooters)
                section.HeadersFooters.Add(headerFooter.Clone(true));
        }
        public int new_counter { get; set; }
        public string new_name { get; set; }
    }
}