using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Windows.Input;
using System.Threading.Tasks;

using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;

using C1.Xaml.Document;

using SSRS.Viewer.App.Common;
using RS = C1.Xaml.ImportServices.ReportingServiceXaml;
using System.Collections.ObjectModel;
using C1.Xaml;

namespace SSRS.Viewer.App
{
    public sealed partial class ReportsPage : Page
    {
        internal static System.Net.NetworkCredential Credentials;
        internal static string ReportServerUrl;

        string _folder;
        NavigationHelper navigationHelper;

        ObservableCollection<RS.CatalogItem> _reportItems;
        bool _connectOnLoad;

        string _prevServerUrl, _prevFolder, _prevUserName, _prevPassword;

        public ReportsPage()
        {
            this.InitializeComponent();

            this.navigationHelper = new NavigationHelper(this);
            this.navigationHelper.LoadState += navigationHelper_LoadState;
            this.navigationHelper.SaveState += navigationHelper_SaveState;

            _reportItems = new ObservableCollection<RS.CatalogItem>();
            reportsList.ItemsSource = _reportItems;

            this.Loaded += ReportsPage_Loaded;

            tbReportServer.Text = "http://ssrs.componentone.com:8000/ReportServer";
            tbFolder.Text = "AdventureWorks";
            tbUserName.Text = "ssrs_demo";
            tbPassword.Password = "bjqveS5gh89BH1Q";
        }

        async void ReportsPage_Loaded(object sender, RoutedEventArgs e)
        {
            UpdatePathLabel();
            if (_connectOnLoad)
            {
                await Connect();
            }
        }

        async void btnConnect_Click(object sender, RoutedEventArgs e)
        {
            await Connect();
        }

        async Task Connect()
        {
            string rsUrl = tbReportServer.Text;
            string folder = tbFolder.Text;
            string userName = tbUserName.Text;
            string pw = tbPassword.Password;
            if (string.IsNullOrEmpty(rsUrl))
            {
                await FocusErr(tbReportServer);
                return;
            }
            if (string.IsNullOrEmpty(userName))
            {
                await FocusErr(tbUserName);
                return;
            }
            if (string.IsNullOrEmpty(pw))
            {
                await FocusErr(tbPassword);
                return;
            }

            loadProgressRing.IsActive = true;
            var credentials = new System.Net.NetworkCredential(userName, pw);
            var co = new C1.Xaml.Ssrs.ConnectionOptions(credentials);

            // ** change AuthenticationType to Basic for the case of local SSRS server
            co.AuthenticationType = C1.Xaml.Ssrs.AuthenticationType.NTLM;

            RS.CatalogItem[] items = null;
            string errMessage = null;

            using (var rs = new C1.Xaml.Ssrs.ServerConnection())
            {
                try
                {
                    rs.SetConnectionOptions(rsUrl, co);
                    items = await rs.ListChildrenAsync("/" + folder, true, System.Threading.CancellationToken.None);
                }
                catch (Exception ex)
                {
                    if (ex.InnerException != null)
                        errMessage = ex.InnerException.Message;
                    else
                        errMessage = ex.Message;
                }
            }
            if (errMessage != null)
            {
                loadProgressRing.IsActive = false;
                await (new Windows.UI.Popups.MessageDialog(errMessage, "Error")).ShowAsync();
                return;
            }

            Credentials = credentials;
            ReportServerUrl = rsUrl;
            _folder = folder;

            _reportItems.Clear();
            foreach (RS.CatalogItem ci in items)
            {
                if (!ci.Hidden && ci.Type == RS.ItemTypeEnum.Report)
                {
                    _reportItems.Add(ci);
                }
            }

            loadProgressRing.IsActive = false;
            reportsTitle.Visibility = Visibility.Visible;
            reportsList.Visibility = Visibility.Visible;
            _connectOnLoad = true;
        }

        async Task FocusErr(Control tb)
        {
            ((Flyout)btnMoreLess.Flyout).ShowAt(btnMoreLess);
            await Dispatcher.RunAsync(CoreDispatcherPriority.Low, async () =>
            {
                while (tb.FocusState == FocusState.Unfocused)
                {
                    await Task.Delay(200);
                    tb.Focus(FocusState.Programmatic);
                }
            });
        }

        void Flyout_Opened(object sender, object e)
        {
            _prevServerUrl = tbReportServer.Text;
            _prevFolder = tbFolder.Text;
            _prevUserName = tbUserName.Text;
            _prevPassword = tbPassword.Password;
        }

        void Flyout_Closed(object sender, object e)
        {
            UpdatePathLabel();
        }

        void btnOkFlyout_Click(object sender, RoutedEventArgs e)
        {
            ((Flyout)btnMoreLess.Flyout).Hide();
        }

        void btnCancelFlyout_Click(object sender, RoutedEventArgs e)
        {
            ((Flyout)btnMoreLess.Flyout).Hide();
            tbReportServer.Text = _prevServerUrl;
            tbFolder.Text = _prevFolder;
            tbUserName.Text = _prevUserName;
            tbPassword.Password = _prevPassword;
        }

        void UpdatePathLabel()
        {
            string rsUrl = tbReportServer.Text;
            string folder = tbFolder.Text;
            txtPathLabel.Text = rsUrl + "/" + folder;
        }

        /// <summary>
        /// Invoked when an item is clicked.
        /// </summary>
        void Reports_ItemClick(object sender, ItemClickEventArgs e)
        {
            RS.CatalogItem item = e.ClickedItem as RS.CatalogItem;
            if (item != null)
            {
                this.Frame.Navigate(typeof(ViewerPage), item.Path);
            }
        }

        /// <summary>
        /// NavigationHelper is used on each page to aid in navigation and 
        /// process lifetime management
        /// </summary>
        public NavigationHelper NavigationHelper
        {
            get { return this.navigationHelper; }
        }

        /// <summary>
        /// Populates the page with content passed during navigation. Any saved state is also
        /// provided when recreating a page from a prior session.
        /// </summary>
        void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
        {
            if (e.PageState != null)
            {
                object obj;
                int n = 0;
                if (e.PageState.TryGetValue("ReportServerUrl", out obj) && obj is string)
                {
                    tbReportServer.Text = (string)obj;
                    n++;
                }
                if (e.PageState.TryGetValue("Folder", out obj) && obj is string)
                {
                    tbFolder.Text = (string)obj;
                    n++;
                }
                if (e.PageState.TryGetValue("UserName", out obj) && obj is string)
                {
                    tbUserName.Text = (string)obj;
                    n++;
                }
                if (e.PageState.TryGetValue("Password", out obj) && obj is string)
                {
                    tbPassword.Password = (string)obj;
                    n++;
                }
                if (n == 4)
                {
                    _connectOnLoad = true;
                }
            }
        }

        void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
        {
            if (_connectOnLoad && e.PageState != null)
            {
                e.PageState["ReportServerUrl"] = ReportServerUrl;
                e.PageState["Folder"] = _folder;
                e.PageState["UserName"] = Credentials.UserName;
                e.PageState["Password"] = Credentials.Password;
            }
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            navigationHelper.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            navigationHelper.OnNavigatedFrom(e);
        }
    }

    /// <summary>
    /// Selects correct template depending on item type
    /// </summary>
    public class CatalogItemTemplateSelector : C1DataTemplateSelector
    {
        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
        {
            RS.CatalogItem ci = item as RS.CatalogItem;
            if (item != null)
            {
                return Resources["Report"] as DataTemplate;
            }
            return base.SelectTemplateCore(item, container);
        }
    }
}
