using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Xml;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using NLog;
namespace DTSXRunner
{
    public class Program
    {
        private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
        static void Main(string[] args)
        {
            string configurationPath = String.Concat(Directory.GetCurrentDirectory(), @"\DTSXPackagesConfiguration.xml");
            if (args.Length > 0) configurationPath = args[0];
            Program p = new Program();
            p.Process(configurationPath);
            Console.ReadKey();
        }

        public bool Process(string dtsxName)
        {
            bool res = true;
            

            return res;
        }

        public bool Process(string configurationPath, Action<string> callback = null)
        {
            bool res = true;
            DateTime startTime = DateTime.Now;
            List<DTSXPackage> myPackages = ReadPackagesFromConfig(configurationPath).ToList();
            bool result;
            bool finishedDueToAnError = false;
            foreach (DTSXPackage package in myPackages)
            {
                result = ExecutePackage(package, callback);
                if (!result && !package.continueOnError)
                {
                    finishedDueToAnError = true;
                    res = false;
                    PrintMessage(String.Concat("Execution stopped due to an error in ", package.absolutePath));
                    break;
                }
            }
            PrintMessage(String.Concat("Process ", ((finishedDueToAnError) ? "FAILED!" : "succeeded"), " - it took ", GetExecutionTime(startTime), " minutes."));
            Console.WriteLine(String.Concat("Press any key to exit"));
            return res;
        }

        string GetExecutionTime(DateTime startTime)
        {
            TimeSpan ts = DateTime.Now.Subtract(startTime);
            int minutes = ts.Hours * 60 + ts.Minutes;
            return minutes.ToString();
        }

        public bool ExecutePackage(string package, string configurationFile, Action<string> callback = null)
        {
            bool success = true;
            PrintMessage(String.Concat("Executing package: ", package), callback);
            try
            {
                Application app = new Application();
                IDTSPackage90 pkg = app.LoadPackage(package, true, null);
                if (configurationFile != String.Empty)
                    pkg.ImportConfigurationFile(configurationFile);
                DTSExecResult pkgResults = pkg.Execute();

                switch (pkgResults)
                {
                    case DTSExecResult.DTSER_FAILURE:
                        success = false;
                        PrintMessage(String.Concat("Executing package FAILED! Result: ", pkgResults.ToString()), callback);
                        break;
                    case DTSExecResult.DTSER_CANCELED:
                        PrintMessage(String.Concat("Executing package CANCELED! Result: ", pkgResults.ToString()), callback);
                        success = false;
                        break;
                    default:
                        PrintMessage(String.Concat("Executing package successeded! Result: ", pkgResults.ToString()), callback);
                        break;
                }
            }
            catch(Exception ex)
            {
                PrintMessage(ex.Message, callback);
                success = false;
            }
            return success;
        }

        bool ExecutePackage(DTSXPackage package, Action<string> callback = null)
        {

            return ExecutePackage(package.absolutePath, package.configuratonFile, callback);
         
        }

        void PrintMessage(string message, Action<string> callback = null)
        {
            string finalMessage = String.Concat("[", DateTime.Now.ToShortTimeString(), "]", message);
            try
            {
                if (callback != null)
                {
                    callback(finalMessage);
                }
                logger.Debugs(message);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.WriteLine(finalMessage);
            }
        }

        IOrderedEnumerable<DTSXPackage> ReadPackagesFromConfig(string fileName)
        {
            List<DTSXPackage> myPackages = new List<DTSXPackage>();
            if (File.Exists(fileName))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(fileName);
                XmlNodeList xnList = doc.SelectNodes("/configurator/package");
                foreach (XmlNode mnode in xnList)
                {
                    if (mnode.Attributes.Count ==  4)
                    {
                        myPackages.Add(new DTSXPackage()
                        {
                            absolutePath = mnode.Attributes["absolutePath"].Value,
                            continueOnError = (mnode.Attributes["continueOnError"].Value == "1"),
                            executionPriority = Int32.Parse(mnode.Attributes["executionPriority"].Value),
                            configuratonFile = 
                                (mnode.Attributes["configurationFile"] == null || mnode.Attributes["configurationFile"].Value == String.Empty)  ? String.Empty : mnode.Attributes["configuratonFile"].Value
                        });
                    }
                }
            }
            return myPackages.OrderBy(o => o.absolutePath).OrderBy(o => o.executionPriority);
        }

    }
}