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

using Windows.ApplicationModel.DataTransfer;
using Windows.UI.ApplicationSettings;
using Windows.UI.Popups;

using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Graphics.Printing;
using Windows.UI.Core;
using Windows.UI.Notifications;

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.Navigation;

using SSRS.Viewer.App.Common;

using RS = C1.Xaml.ImportServices.ReportingServiceXaml;
using C1.Xaml.Document;
using C1.Xaml.SsrsViewer;

using SSRS.Viewer.App.Notifications.ToastContent;

namespace SSRS.Viewer.App
{
    public sealed partial class ViewerPage : Page
    {
        SsrsNavigationTarget _target;
        NavigationHelper navigationHelper;
        bool printTaskAssigned;
        bool settingsPaneBound;

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

        public ViewerPage()
        {
            this.InitializeComponent();

            // Setup the navigation helper
            navigationHelper = new NavigationHelper(this);
            navigationHelper.LoadState += navigationHelper_LoadState;
            navigationHelper.SaveState += navigationHelper_SaveState;

            this.searchBar.Viewer = ssrsViewer;

            ssrsViewer.OpenSubreport += ssrsViewer_OpenSubreport;
            ssrsViewer.FileSavedNotification += ssrsViewer_FileSavedNotification;

            // Setup the logical page navigation components that allow
            // the page to only show one pane at a time.
            navigationHelper.GoBackCommand = new RelayCommand(() => this.GoBack(), () => this.CanGoBack());
            navigationHelper.GoForwardCommand = new RelayCommand(() => this.GoForward(), () => this.CanGoForward());

            this.Loaded += ViewerPage_Loaded;
            this.Unloaded += ViewerPage_Unloaded;
        }

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

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

        bool CanGoBack()
        {
            return navigationHelper.CanGoBack();
        }

        void GoBack()
        {
            UnsubscribeFromManagers();
            navigationHelper.GoBack();
        }

        bool CanGoForward()
        {
            return navigationHelper.CanGoForward();
        }

        void GoForward()
        {
            UnsubscribeFromManagers();
            navigationHelper.GoForward();
        }

        void ssrsViewer_FileSavedNotification(object sender, FileSavedNotificationEventArgs e)
        {
            IToastText02 toastContent = ToastContentFactory.CreateToastText02();
            toastContent.TextHeading.Text = e.NotificationHeader;
            toastContent.TextBodyWrap.Text = e.FilePath;

            ToastNotification toast = toastContent.CreateNotification();
            ToastNotificationManager.CreateToastNotifier().Show(toast);
        }

        void ssrsViewer_OpenSubreport(object sender, NavigationTargetEventArgs e)
        {
            UnsubscribeFromManagers();
            this.Frame.Navigate(typeof(ViewerPage), e.SsrsTarget.EncodeAsString());
        }

        /// <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 (!printTaskAssigned)
            {
                PrintManager.GetForCurrentView().PrintTaskRequested += ViewerPage_PrintTaskRequested;
                printTaskAssigned = true;
            }
            if (!settingsPaneBound)
            {
                SettingsPane.GetForCurrentView().CommandsRequested += ViewerPage_CommandsRequested;
                settingsPaneBound = true;
            }
            ssrsViewer.Credential = ReportsPage.Credentials;

            // ** uncomment the following line for the case of local SSRS server
            //ssrsViewer.AuthenticationType = C1.Xaml.Ssrs.AuthenticationType.Basic;

            var target = SsrsNavigationTarget.LoadFromPageState(e.PageState);
            if (target == null)
            {
                string s = e.NavigationParameter as string;
                if (!string.IsNullOrEmpty(s))
                {
                    target = SsrsNavigationTarget.DecodeFromString(s);
                    if (target == null)
                    {
                        ssrsViewer.ReportServer = ReportsPage.ReportServerUrl;
                        ssrsViewer.ReportPath = s;
                    }
                }
            }
            _target = target;
        }

        async void ViewerPage_Loaded(object sender, RoutedEventArgs e)
        {
            if (_target != null && _target.Location != null)
            {
                await ssrsViewer.Open(_target);
            }
            pageTitle.Text = ssrsViewer.ReportTitle;
        }

        void ViewerPage_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs e)
        {
            var pageSettingsCommand = new SettingsCommand(Guid.Empty, "Page Settings",
                (command) =>
                {
                    ssrsViewer.PageSettingsFlyout.Show();
                });
            e.Request.ApplicationCommands.Add(pageSettingsCommand);
        }

        /// <summary>
        /// Preserves state associated with this page in case the application is suspended or the
        /// page is discarded from the navigation cache.  Values must conform to the serialization
        /// requirements of <see cref="SuspensionManager.SessionState"/>.
        /// </summary>
        void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
        {
            var target = ssrsViewer.GetSsrsTarget();
            if (target != null)
            {
                target.SaveToPageState(e.PageState);
            }
        }

        void ViewerPage_Unloaded(object sender, RoutedEventArgs e)
        {
            UnsubscribeFromManagers();
            ssrsViewer.Close();
        }

        void UnsubscribeFromManagers()
        {
            if (printTaskAssigned)
            {
                PrintManager.GetForCurrentView().PrintTaskRequested -= ViewerPage_PrintTaskRequested;
                printTaskAssigned = false;
            }
            if (settingsPaneBound)
            {
                SettingsPane.GetForCurrentView().CommandsRequested -= ViewerPage_CommandsRequested;
                settingsPaneBound = false;
            }
            _target = null;
        }

        async void ViewerPage_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
        {
            await ssrsViewer.CreatePrintTaskAsync(args);
        }

        internal void App_Suspending()
        {
            ssrsViewer.HandleSuspending();
        }

        void CommandBar_Opened(object sender, object e)
        {
            searchBar.FocusSearchBox();
        }

        void btnClose_Click(object sender, RoutedEventArgs e)
        {
            BottomAppBar.IsOpen = false;
            searchBar.ResetSearch();
        }

        void AppBarToggleButton_Click(object sender, RoutedEventArgs e)
        {
            BottomAppBar.IsOpen = false;
        }

        void btnCopy_Click(object sender, RoutedEventArgs e)
        {
            string s = ssrsViewer.GetSelectedText();
            if (!string.IsNullOrEmpty(s))
            {
                DataPackage dp = new DataPackage();
                dp.RequestedOperation = DataPackageOperation.Copy;
                dp.SetText(s);
                Clipboard.SetContent(dp);
                BottomAppBar.IsOpen = false;
            }
        }
    }
}