/// <summary>
 /// Initializes a new instance of the <see cref="TaskWrapper"/> class.
 /// </summary>
 /// <param name="dllFile">The path to the assembly file.</param>
 /// <param name="taskModule">The task instance.</param>
 /// <param name="configurationData">The configuration data.</param>
 /// <param name="logger">The proxy to the remote logger.</param>
 internal TaskWrapper(string dllFile, ITaskModule taskModule, TaskConfigurationData configurationData, ILogger logger)
 {
     this._dllFile = dllFile;
     this._task = taskModule;
     this._logger = logger;
     this._configurationData = configurationData;
     this._taskName = taskModule.GetType().FullName;
 }
        /// <summary>
        /// Loads a configuration file.
        /// </summary>
        /// <param name="fileName">The path to the configuration file.</param>
        /// <returns>The configuration information.</returns>
        public static IEnumerable<TaskConfigurationData> LoadFrom(string fileName)
        {
            XDocument doc = XDocument.Load(fileName, LoadOptions.SetLineInfo);

            XElement root = doc.Root;

            if (null == root || root.Name != ConfigurationHelpers.ConfigRootElementName)
            {
                throw new InvalidConfigurationException("Invalid configuration file content.");
            }

            var taskElements = root.Elements(ConfigurationHelpers.ConfigTaskElementName);

            List<TaskConfigurationData> taskConfigurations = new List<TaskConfigurationData>();

            foreach (XElement taskElement in taskElements)
            {
                TaskConfigurationData cfg = new TaskConfigurationData();

                #region Task type

                try
                {
                    cfg.TypeName = (string)taskElement.Attribute(ConfigurationHelpers.ConfigTypeAttributeName);
                }
                catch
                {
                    throw new InvalidConfigurationException(taskElement.MakeValueErrorMessage(ConfigurationHelpers.ConfigTypeAttributeName));
                }

                #endregion

                if (string.IsNullOrWhiteSpace(cfg.TypeName)) 
                {
                    throw new InvalidConfigurationException(ConfigurationHelpers.MakeValueErrorMessage(taskElement, ConfigurationHelpers.ConfigTypeAttributeName));
                }

                string cultureName = (string)taskElement.Attribute(ConfigurationHelpers.ConfigCultureAttributeName);

                if (!string.IsNullOrWhiteSpace(cultureName))
                {
                    CultureInfo info = CultureInfo.GetCultureInfo(cultureName);

                    if (null != info)
                    {
                        cfg.Culture = info;
                    }
                }

                cfg.ApplyCommonInfoFromElement(taskElement);

                try
                {
                    cfg.DelayStart = ((string)taskElement.Attribute(ConfigurationHelpers.ConfigDelayStartName)).ToTimeSpan();
                }
                catch
                {
                    throw new InvalidConfigurationException(taskElement.MakeValueErrorMessage(ConfigurationHelpers.ConfigDelayStartName));
                }

                XElement scheduleList;

                #region Schedule list

                try
                {
                    scheduleList = taskElement.Elements(ConfigurationHelpers.ConfigScheduleListElementName).SingleOrDefault();
                }
                catch
                {
                    throw new InvalidConfigurationException(taskElement.MakeElementErrorMessage("Task configuration has too many schedule lists."));
                }

                #endregion

                List<ScheduleData> scheds = new List<ScheduleData>();

                if (scheduleList != null)
                {
                    foreach (XElement scheduleElement in scheduleList.Elements(ConfigurationHelpers.ConfigScheduleItemElementName))
                    {
                        ScheduleData sched = new ScheduleData();

                        #region From

                        try
                        {
                            sched.From = ((string)scheduleElement.Attribute(ConfigurationHelpers.ConfigFromAttributeName)).ToTimeSpan().Value;
                        }
                        catch
                        {
                            throw new InvalidConfigurationException(scheduleElement.MakeValueErrorMessage(ConfigurationHelpers.ConfigFromAttributeName));
                        }

                        #endregion From

                        #region To

                        try
                        {
                            sched.To = ((string)scheduleElement.Attribute(ConfigurationHelpers.ConfigToAttributeName)).ToTimeSpan().Value;
                        }
                        catch
                        {
                            throw new InvalidConfigurationException(scheduleElement.MakeValueErrorMessage(ConfigurationHelpers.ConfigToAttributeName));
                        }

                        #endregion To

                        sched.ApplyCommonInfoFromElement(scheduleElement);

                        scheds.Add(sched);
                    }
                }

                cfg.Schedule = scheds.OrderBy(s => s.From).ToList().AsReadOnly();

                TimeSpan? tempFrom = null, tempTo = null;
                foreach (ScheduleData d in cfg.Schedule)
                {
                    if (null == tempFrom && null == tempTo)
                    {
                        tempFrom = d.From;
                        tempTo = d.To;
                        continue;
                    }

                    if ((tempFrom <= d.From && d.From < tempTo) || (tempFrom <= d.To && d.To < tempTo))
                    {
                        throw new InvalidConfigurationException(taskElement.MakeElementErrorMessage(string.Format("Schedule {0}-{1} conflicts with another schedule for this configuration", d.From, d.To)));
                    }
                }

                #region Configuration

                try
                {
                    XElement cfig = taskElement.Elements(ConfigurationHelpers.ConfigModuleConfigurationElementName).SingleOrDefault();

                    if (null != cfig)
                    {
                        cfg.ConfigurationData = cfig.ToString();
                    }
                }
                catch
                {
                    throw new InvalidConfigurationException(taskElement.MakeElementErrorMessage("Task configuration has too many module configuration elements."));
                }

                #endregion

                taskConfigurations.Add(cfg);
            }

            return taskConfigurations.AsReadOnly();
        }