using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.Common.Utilities;
using MECF.Framework.UI.Client.ClientBase;
using OpenSEMI.ClientBase.Command;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using Caliburn.Micro.Core;
using OpenSEMI.ClientBase;
using Sicentury.Core.Collections;

namespace MECF.Framework.UI.Client.CenterViews.DataLogs.Event
{
    public class EventViewModel : BaseModel
    {
        #region Variables

        /// <summary>
        /// 首次查询。需要计算总页码等参数。
        /// </summary>
        private const int QUERY_FIRST_TIME = -1;

        /// <summary>
        /// 一次性查询所有数据，EXCEL导出使用。
        /// </summary>
        private const int QUERY_FOR_EXCEL_EXPORT = 0;

        /// <summary>
        /// 指示函数<see cref="tbLoadPort1Selection"/>是否发生了重入。如果发生重入，说明“ALL”由
        /// 后台程序勾选，此时不要进行任何逻辑操作，仅设置”ALL“的选择状态。
        /// 重入的情况发生在：
        /// 1. 所有选项全部被选中
        /// 2. 此时将“ALL”以外的选项勾掉
        /// 3. “ALL”自动取消选择
        /// 上述2会触发3，引起函数重入。
        /// </summary>
        private bool _isEventSourceFilterSelectionReentered = false;

        private int _currentPage;
        private int _totalPage;
        private int _selectedPage;
        private int _selectedPaginationCapacity;
        private bool _isLoading;
        private bool _isExporting;
        private string _exportingMessage;

        /// <summary>
        /// 显示查询到的事件日志列表。
        /// </summary>
        private readonly IProgress<List<EventItem>> _progShowSearchingResult;

        /// <summary>
        /// 构造Event Source列表。
        /// </summary>
        private readonly IProgress<List<string>> _progConstructEventSourcesList;

        /// <summary>
        /// 更新分页信息。
        /// <para>Tuple.Item1: 当前页号</para>
        /// <para>Tuple.Item2: 总页号；设置为-1时表示忽略更新总页号。</para>
        /// </summary>
        private readonly IProgress<Tuple<int, int>> _progUpdatePaginationInfo;

        /// <summary>
        /// 更新查询状态。
        /// </summary>
        private readonly IProgress<bool> _progUpdateQueryStatus;

        /// <summary>
        /// 更新日志导出状态。
        /// <para>Tuple.Item1: 导出进度，0~100</para>
        /// <para>Tuple.Item2: 消息</para>
        /// </summary>
        private readonly IProgress<Tuple<int, string>> _progUpdateExportingState;

        #endregion

        #region Constructors

        public EventViewModel()
        {
            DisplayName = "Event";

            QueryEventList = () =>
            {
                var result = new List<string>();

                foreach (var eventName in Enum.GetNames(typeof(EventEnum)))
                    result.Add(eventName);

                return result;
            };

            SearchedResult = new ObservableRangeCollection<SystemLogItem>();
            FilterEventSources = new ObservableRangeCollection<string>();
            SelectedFilterEventSource = new ObservableRangeCollection<string>();
            PaginationSource = new ObservableRangeCollection<int>();

            SearchKeyWords = string.Empty;

            SearchAlarmEvent = true;
            SearchWarningEvent = true;
            SearchInfoEvent = true;
            SearchOpeLog = false;

            SearchPMA = false;
            SearchPMB = false;
            SearchPMC = false;
            SearchPMD = false;
            SearchTM = false;
            SearchLL = false;
            SearchSystem = false;
            
            tbLoadPort1SelectionChangedCommand = new BaseCommand<object>(tbLoadPort1Selection);
            

            // 分页支持的每页Log数量
            //! 最小每页条目数使用30，以保证正好显示一页而不出现纵向滚动条。
            PaginationCapacity = new List<int>
            {
                30,
                300,
                3000
            };

            _selectedPaginationCapacity = PaginationCapacity.Last();
            _totalPage = 1;
            _currentPage = 1;

            NavigateCommand = new BaseCommand<string>(Navigate, (o) => true);

            #region 显示查询到的EventLog列表

            _progShowSearchingResult = new Progress<List<EventItem>>((queryRet =>
            {
                if (SearchedResult == null)
                    SearchedResult = new ObservableRangeCollection<SystemLogItem>();
                else
                    SearchedResult.Clear();

                SearchedResult.AddRange(queryRet.Select(x =>
                    new SystemLogItem()
                    {
                        Time = (x.OccuringTime).ToString("yyyy/MM/dd HH:mm:ss.fff"),
                        LogType = x.Level.ToString(),
                        Detail = x.Description,
                        TargetChamber = x.Source,
                        Initiator = "",
                        Icon = new BitmapImage(new Uri(
                            $"pack://application:,,,/MECF.Framework.UI.Core;component/Resources/SystemLog/{x.Level}.png",
                            UriKind.Absolute))
                    }
                ));
            }));

            #endregion

            #region 构造Event Sources列表

            _progConstructEventSourcesList = new Progress<List<string>>((list =>
            {
                SelectedFilterEventSource.Clear();
                FilterEventSources.Clear();

                SelectedFilterEventSource.Add("ALL");
                FilterEventSources.Add("ALL");

                SelectedFilterEventSource.AddRange(list);
                FilterEventSources.AddRange(list);

            }));

            #endregion

            #region 更新分页信息

            _progUpdatePaginationInfo = new Progress<Tuple<int, int>>(pageInfo =>
            {
                _currentPage = pageInfo.Item1;

                if (pageInfo.Item2 > 0)
                {
                    _totalPage = pageInfo.Item2;
                    PaginationSource.Clear();
                    PaginationSource.AddRange(Enumerable.Range(1, _totalPage));
                    NotifyOfPropertyChange(nameof(PaginationSource));
                }

                NotifyOfPropertyChange(nameof(PageInfo));

                _selectedPage = _currentPage;
                NotifyOfPropertyChange(nameof(SelectedPage));
            });

            #endregion

            #region 更新查询状态

            _progUpdateQueryStatus = new Progress<bool>(isBusy =>
            {
                IsLoading = isBusy;
            });

            #endregion

            #region 更新日志导出进度信息

            _progUpdateExportingState = new Progress<Tuple<int, string>>(state =>
            {
                var progress = state.Item1;
                var message = state.Item2;

                switch (progress)
                {
                    case 0:
                        IsExporting = true;
                        break;

                    case 100:
                        IsExporting = false;
                        break;
                }

                ExportingMessage = message;
            });

            #endregion
        }

        #endregion

        #region Properties

        public bool SearchAlarmEvent { get; set; }

        public bool SearchWarningEvent { get; set; }

        public bool SearchInfoEvent { get; set; }

        public bool SearchOpeLog { get; set; }

        public bool SearchPMA { get; set; }

        public bool SearchPMB { get; set; }

        public bool SearchPMC { get; set; }

        public bool SearchPMD { get; set; }

        //public bool SearchCoolDown { get; set; }
        public bool SearchTM { get; set; }

        public bool SearchLL { get; set; }

        //public bool SearchBuf1 { get; set; }
        public bool SearchSystem { get; set; }

        public string SearchKeyWords { get; set; }

        public string FilterKeyWords { get; set; }

        public DateTime SearchBeginTime
        {
            get => ((EventView)view).wfTimeFrom.Value;
            set
            {
                ((EventView)view).wfTimeFrom.Value = value;
                NotifyOfPropertyChange(nameof(SearchBeginTime));
            }
        }

        public DateTime SearchEndTime
        {
            get => ((EventView)view).wfTimeTo.Value;
            set
            {
                ((EventView)view).wfTimeTo.Value = value;
                NotifyOfPropertyChange(nameof(SearchEndTime));
            }
        }

        public List<string> EventList { get; set; }

        public string SelectedEvent { get; set; }

        public ObservableRangeCollection<SystemLogItem> SearchedResult { get; private set; }

        public Func<List<string>> QueryEventList { get; set; }
        

        private EventView view;

        public ObservableRangeCollection<string> FilterEventSources { get; set; }

        public ObservableRangeCollection<string> SelectedFilterEventSource { get; set; }

        public ICommand tbLoadPort1SelectionChangedCommand { get; set; }
        //public ICommand tbLoadPort2SelectionChangedCommand { get; set; }

        public ICommand NavigateCommand { get; set; }

        /// <summary>
        /// 返回受支持的分页每页容量。
        /// </summary>
        public List<int> PaginationCapacity { get; }

        /// <summary>
        /// 页码列表，用于快速跳转页面下拉框数据源。
        /// </summary>
        public ObservableRangeCollection<int> PaginationSource { get; }

        public int SelectedPage
        {
            get => _selectedPage;
            set
            {
                _selectedPage = value;
                Query(_selectedPage);
            }
        }

        /// <summary>
        /// 返回选择的分页每页容量。
        /// </summary>
        public int SelectedPaginationCapacity
        {
            get => _selectedPaginationCapacity;
            set
            {
                _selectedPaginationCapacity = value;
                Query();
            }
        }

        /// <summary>
        /// 页码信息。
        /// </summary>
        public string PageInfo => $"{_currentPage}/{_totalPage}";

        /// <summary>
        /// 返回是否正在加载数据。
        /// </summary>
        public bool IsLoading
        {
            get => _isLoading;
            set
            {
                _isLoading = value;
                NotifyOfPropertyChange(nameof(IsLoading));
            }
        }

        /// <summary>
        /// 是否正在导出数据。
        /// </summary>
        public bool IsExporting
        {
            get => _isExporting;
            private set
            {
                _isExporting = value;
                NotifyOfPropertyChange(nameof(IsExporting));
            }
        }

        /// <summary>
        /// 导出进度消息。
        /// </summary>
        public string ExportingMessage
        {
            get => _exportingMessage;
            private set
            {
                _exportingMessage = value;
                NotifyOfPropertyChange(nameof(ExportingMessage));
            }
        }

        #endregion

        #region Methods

        public void Navigate(string args)
        {
            switch (args)
            {
                case "first":
                    if (_currentPage == 1)
                        return;
                    _currentPage = 1;
                    break;

                case "previous":
                    if(_currentPage > 1)
                        _currentPage--;
                    break;

                case "next":
                    if(_currentPage < _totalPage)
                        _currentPage++;
                    break;

                case "last":
                    if (_currentPage == _totalPage)
                        return;
                    _currentPage = _totalPage;
                    break;

                default:
                    return;
            }

            Query(_currentPage);
        }

        protected override void OnViewLoaded(object view)
        {
            base.OnViewLoaded(view);

            // 默认的查询时间设置为当天
            this.view = (EventView)view;
            SearchBeginTime = DateTime.Today;
            SearchEndTime = DateTime.Today.AddDays(1).AddTicks(-1);
            Preload();
        }

        public void Preload()
        {
            EventList = new List<string> { "All" };

            if (QueryEventList != null)
            {
                var evList = QueryEventList();
                foreach (var ev in evList)
                    EventList.Add(ev);
            }

            SelectedEvent = "All";
            
            Query();
        }

        /// <summary>
        /// Event Source中全选和全不选逻辑实现。
        /// <see cref="_isEventSourceFilterSelectionReentered"/>
        /// </summary>
        /// <param name="o"></param>
        public void tbLoadPort1Selection(object o)
        {
            if (_isEventSourceFilterSelectionReentered)
                return;

            _isEventSourceFilterSelectionReentered = true;

            if (o is ItemSelectionData item)
            {
                if (item.SelectItem == "ALL")
                {
                    //if (isAllSelectedInBackend)
                    //    return;

                    if (item.IsSelect)
                    {
                        SelectedFilterEventSource.Clear();
                        SelectedFilterEventSource.AddRange(FilterEventSources);
                        //FilterEventSources.ToList().ForEach(sp =>
                        //{
                        //    if (!SelectedFilterEventSource.Contains(sp)) 
                        //        SelectedFilterEventSource.Add(sp);
                        //});
                    }
                    else
                    {
                        SelectedFilterEventSource.Clear();
                    }
                }
                else
                {
                    // 判断是否需要取消或选中“ALL”
                    var list = 
                        FilterEventSources
                            .Except(new[] {"ALL"})
                            .Except(SelectedFilterEventSource.Except(new [] {"ALL"}))
                            .ToList();

                    //isAllSelectedInBackend = true;

                    if (list.Any())
                    {
                        if (SelectedFilterEventSource.Contains("ALL"))
                            SelectedFilterEventSource.Remove("ALL");

                    }
                    else
                    {
                        SelectedFilterEventSource.Clear();
                        SelectedFilterEventSource.AddRange(FilterEventSources);
                        //FilterEventSources.ToList().ForEach(sp =>
                        //{
                        //    if (!SelectedFilterEventSource.Contains(sp))
                        //        SelectedFilterEventSource.Add(sp);
                        //});
                    }

                    //isAllSelectedInBackend = false;
                }
            }

            _isEventSourceFilterSelectionReentered = false;
        }
        
        private string GetSourceWhere()
        {
            return "";
        }

        #region 数据库查询相关函数

        #region SQL 语句构造函数

        /// <summary>
        /// 获取EventLog查询语句中select部分表达式。
        /// </summary>
        private string GetEventLogQuerySql()
        {
            return
                "SELECT \"event_id\", \"event_enum\", \"type\", \"occur_time\", \"level\",\"source\" , \"description\" FROM \"event_data\"" +
                GetWhereTimeRangeExpression();
        }

        /// <summary>
        /// 获取EventLog行数查询语句中select部分表达式。
        /// </summary>
        private string GetEventLogCountSql()
        {
            return
                "SELECT COUNT(1) FROM \"event_data\"" + GetWhereTimeRangeExpression(); ;
        }

        /// <summary>
        /// 获取EventLog行数查询语句中select部分表达式。
        /// </summary>
        private string GetChamberListSql()
        {
            return
                "SELECT DISTINCT \"source\" FROM \"event_data\"" + GetWhereTimeRangeExpression();
        }

        /// <summary>
        /// 获取WHERE条件中的“时间范围”子句。
        /// <para>注意：所有Select语句构造时必须包含TimeRange条件。</para>
        /// </summary>
        /// <returns></returns>
        private string GetWhereTimeRangeExpression()
        {

            var sql = new StringBuilder(
                $" WHERE \"occur_time\" BETWEEN '{SearchBeginTime:yyyy/MM/dd HH:mm:ss}' AND '{SearchEndTime:yyyy/MM/dd HH:mm:ss}'");

            return sql.ToString();
        }

        /// <summary>
        /// 获取WHERE条件中的“Log Level”子句。
        /// </summary>
        /// <returns></returns>
        private string GetWhereLevelExpression()
        {
            var sqlLevelConditions = new List<string>();
            if (SearchInfoEvent)
                sqlLevelConditions.Add("'Information'");

            if (SearchWarningEvent)
                sqlLevelConditions.Add("'Warning'");

            if (SearchAlarmEvent)
                sqlLevelConditions.Add("'Alarm'");

            return $" AND (\"level\" in ({string.Join(",", sqlLevelConditions)}))";
        }

        /// <summary>
        /// 获取WHERE条件中的“关键字”子句。
        /// </summary>
        /// <returns></returns>
        private string GetWhereQueryKeyWordsExpression()
        {
            return string.IsNullOrEmpty(SearchKeyWords)
                ? ""
                : $" AND (lower(\"description\") like lower('%{SearchKeyWords}%'))";
        }

        /// <summary>
        /// 获取WHERE条件中的“事件类型过滤条件“子句。
        /// </summary>
        /// <returns></returns>
        private string GetWhereFilterEventSourceExpression()
        {
            if (SelectedFilterEventSource == null || SelectedFilterEventSource.Count <= 0)
                throw new ArgumentOutOfRangeException(nameof(SelectedFilterEventSource),
                    "no event source(s) in filter are selected.");

            if (SelectedFilterEventSource.Contains("ALL"))
                return "";

            return $" AND (\"source\" in ({string.Join(",", SelectedFilterEventSource.Select(x => $"'{x}'"))}))";
        }

        /// <summary>
        /// 获取WHERE条件中的“事件描述关键字过滤条件“子句。
        /// </summary>
        /// <returns></returns>
        private string GetWhereFilterEventKeywordExpression()
        {
            return string.IsNullOrEmpty(FilterKeyWords)
                ? ""
                : $" AND (lower(\"description\") like lower('%{FilterKeyWords}%'))";
        }

        /// <summary>
        /// 获取SQL查询语句中的分页表达式。
        /// </summary>
        /// <param name="countPerPage"></param>
        /// <param name="currentPage"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        private string GetPaginationExpression(int countPerPage, int currentPage)
        {
            if (countPerPage <= 0)
                throw new ArgumentOutOfRangeException(nameof(countPerPage),
                    "the amount items per page can not be less than 1.");

            if (currentPage <= 0)
                throw new ArgumentOutOfRangeException(nameof(currentPage),
                    "the current page required can not be less than 1.");



            return $" ORDER BY \"occur_time\" LIMIT {countPerPage} OFFSET {countPerPage * (currentPage - 1)}";
        }

        #endregion

        /// <summary>
        /// 查询当前条件下共有多少行数据。
        /// <param name="isIncludeFilter">是否包含过滤条件。</param>
        /// </summary>
        private int QueryRowAmount(bool isIncludeFilter)
        {
            var sql = GetEventLogCountSql() 
                      + GetWhereLevelExpression()
                      + GetWhereQueryKeyWordsExpression();

            if (isIncludeFilter)
                sql += GetWhereFilterEventSourceExpression()
                    + GetWhereFilterEventKeywordExpression();

            var dt = QueryDataClient.Instance.Service.QueryData(sql);

            // 未查询到任何数据。
            if (dt == null || dt.Rows.Count <= 0 || dt.Columns.Count <= 0)
                return 0;

            // 返回满足当前条件的行数。
            return int.Parse(dt.Rows[0][0].ToString());
        }

        /// <summary>
        /// 查询Event源列表。
        /// <para>注意：该查询仅在首次查询时使用；语句的条件仅只用时间范围和事件类型，不包含Filter选项。</para>
        /// <para>当套用Filter选项查询、或分页查询时，不再重构Event源列表。</para>
        /// </summary>
        /// <returns></returns>
        private List<string> QueryEventSources()
        {
            var chamberList = new List<string>();

            var sql = GetChamberListSql() + GetWhereLevelExpression();
            var dt = QueryDataClient.Instance.Service.QueryData(sql);

            // 未查询到任何数据。
            if (dt == null || dt.Rows.Count <= 0 || dt.Columns.Count <= 0)
                return chamberList;

            // 返回满足当前条件的行数。
            chamberList.AddRange(from DataRow row in dt.Rows select row[0].ToString());

            return chamberList;
        }

        /// <summary>
        /// 查询符合条件的事件日志。
        /// </summary>
        /// <param name="page">待查询页码。0:查询所有数据而不分页；其它：查询指定的页码。</param>
        /// <param name="isIncludeFilter">是否包含过滤条件。</param>
        /// <exception cref="ArgumentOutOfRangeException">页码错误，页码必须为大于等于0的整数。</exception>
        /// <returns></returns>
        private List<EventItem> QueryEventLogs(int page, bool isIncludeFilter)
        {
            if (page < 0)
                throw new ArgumentOutOfRangeException(nameof(page), "the page number must be greater than 0.");

            var sql = GetEventLogQuerySql()
                      + GetWhereLevelExpression()
                      + GetWhereQueryKeyWordsExpression();

            if (isIncludeFilter)
                sql += GetWhereFilterEventSourceExpression()
                       + GetWhereFilterEventKeywordExpression();

            // page == 0 表示查询所有数据，仅导出Excel时使用。
            if(page > 0)
                sql += GetPaginationExpression(SelectedPaginationCapacity, page);

            return QueryDataClient.Instance.Service.QueryDBEvent(sql);
        }

        /// <summary>
        /// 查询数据。
        /// </summary>
        /// <param name="page">待查询的页号</param>
        /// <param name="isIncludeFilter">是否包含过滤条件。</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public void Query(int page = QUERY_FIRST_TIME, bool isIncludeFilter = false)
        {
            if (IsLoading)
                return;

            if (SearchBeginTime > SearchEndTime)
            {
                DialogBox.ShowError("Time range invalid, start time should be early than end time");
                return;
            }


            Task.Run(() =>
            {
                var searchingResult = new List<EventItem>();

                try
                {
                    // 查询开始
                    _progUpdateQueryStatus.Report(true);

                    if (page <= QUERY_FIRST_TIME) // Query按钮按下，或首次加载界面
                    {
                        // 统计总页数
                        var rowCount = QueryRowAmount(isIncludeFilter);

                        var totalPage = (int)Math.Ceiling(rowCount / (double)SelectedPaginationCapacity);

                        // 首次查询第一页
                        searchingResult = QueryEventLogs(1, isIncludeFilter);

                        if (isIncludeFilter == false)
                        {
                            // 构造Event Sources列表，仅在首次查询时构造
                            var eventSources = QueryEventSources();
                            _progConstructEventSourcesList.Report(eventSources);
                        }

                        // 更新页面信息
                        _progUpdatePaginationInfo.Report(new Tuple<int, int>(1, totalPage));


                    }
                    else if (page == QUERY_FOR_EXCEL_EXPORT)
                    {

                    }
                    else if (page >= 1)
                    {
                        // 翻页按钮按下
                        searchingResult = QueryEventLogs(page, isIncludeFilter);

                        // 更新页面信息
                        _progUpdatePaginationInfo.Report(new Tuple<int, int>(page, -1));

                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(nameof(page), "invalid page number.");
                    }
                }
                catch (Exception ex)
                {
                    searchingResult.Clear();
                    Execute.OnUIThread(() =>
                    {
                        DialogBox.ShowError($"Failed to query event log, {ex.Message}");
                    });
                }
                finally
                {
                    // 显示结果
                    _progShowSearchingResult.Report(searchingResult);

                    // 查询完毕
                    _progUpdateQueryStatus.Report(false);
                }
            });
        }

        /// <summary>
        /// 导出
        /// </summary>
        public async void Export()
        {
            try
            {
                var dlg = new Microsoft.Win32.SaveFileDialog();
                dlg.DefaultExt = ".xlsx"; // Default file extension 
                dlg.FileName = $"Operation Log_{DateTime.Now:yyyyMMdd_HHmmss}";
                dlg.Filter = "Excel数据表格文件(*.xlsx)|*.xlsx"; // Filter files by extension 
                var result = dlg.ShowDialog(); // Show open file dialog box

                if (result != true) 
                    return;

                await Task.Run(() =>
                {

                    _progUpdateExportingState.Report(new Tuple<int, string>(0, "Querying data ..."));

                    // 查询数据
                    var queryRet = QueryEventLogs(0, false);
                    if (queryRet == null || queryRet.Count <= 0)
                        throw new Exception("no event logs are found, please change the conditions and retry.");


                    var ds = new DataSet();
                    ds.Tables.Add(new System.Data.DataTable("系统运行日志"));
                    ds.Tables[0].Columns.Add("Type");
                    ds.Tables[0].Columns.Add("Time");
                    ds.Tables[0].Columns.Add("System");
                    ds.Tables[0].Columns.Add("Content");

                    var currRow = 0;
                    var totalRow = queryRet.Count;
                    foreach (var item in queryRet)
                    {
                        currRow++;

                        _progUpdateExportingState.Report(new Tuple<int, string>(50,
                            $"Exporting item {currRow}/{totalRow} ..."));

                        var row = ds.Tables[0].NewRow();
                        row[0] = item.Level;
                        row[1] = item.OccuringTime.ToString("yyyy/MM/dd HH:mm:ss.fff");
                        row[2] = item.Source;
                        row[3] = item.Description;
                        ds.Tables[0].Rows.Add(row);
                    }

                    _progUpdateExportingState.Report(new Tuple<int, string>(60, "Writing excel file ..."));
                    if (!ExcelHelper.ExportToExcel(dlg.FileName, ds, out var reason))
                        throw new InvalidOperationException($"Export failed, {reason}");

                    _progUpdateExportingState.Report(new Tuple<int, string>(100, "Done!"));
                });

                MessageBox.Show($"Export succeed, file save as {dlg.FileName}", "Export", MessageBoxButton.OK,
                    MessageBoxImage.Information);
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                MessageBox.Show("导出系统日志发生错误", "导出失败", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            finally
            {
                _progUpdateExportingState.Report(new Tuple<int, string>(100, "Done!"));
            }
        }

        #endregion

        #endregion
    }
}