using Http.Core;
using Microsoft.Toolkit;
using PCUT.Entities;
using PCUT.ViewModels;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
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 Http.Core.Extensions;
using static Http.Core.Constants.HttpConstants;
using static PCUT.App;
using Windows.UI.Core;
using System.Threading;
using PCUT.Models;
using Http.Core.Exceptions;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238

namespace PCUT.Pages
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class FileManagerPage : Page
    {
        private FileListViewModel ViewModels { get; set; }
        public FileManagerPage()
        {
            this.InitializeComponent();
            ViewModels = DataContext as FileListViewModel;

            ViewModels.SetFilterMetadataOnFileChange();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            ViewModels.Categories = new SelectableCollection<Category>(new Category { Name = "-None-" });
            base.OnNavigatedTo(e);
        }

        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            ViewModels.MetadataModel.BindAll(Type, Brand, null, null, null, Year);
            ViewModels.Categories.Bind(Categories);

            await ViewModels.GetCategoriesAsync();
            await ViewModels.MetadataModel.LoadAllMetadataAsync();
            ViewModels.Pagination.Page = 1;
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            ViewModels.Pagination.Dispose();
        }

        private async void AddFile_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new FileAddDialog();
            var result = await dialog.ShowAsync();
            if (result == ContentDialogResult.Primary)
                await ViewModels.Reload();
        }

        private async void EditFile_Click(object sender, RoutedEventArgs e)
        {
            if (sender is Button button && button.CommandParameter is string fileId)
            {
                if (CanEditFile())
                {
                    var dialog = new FileEditDialog(fileId);
                    var result = await dialog.ShowAsync();
                    if (result == ContentDialogResult.Primary)
                        await ViewModels.Reload();
                    _editFileFlag = false;
                }
            }
        }

        private static readonly object _editFileLock = new object();
        private static bool _editFileFlag = false;
        private bool CanEditFile()
        {
            if (!Monitor.TryEnter(_editFileLock))
                return false;

            try
            {
                if (_editFileFlag)
                    return false;

                _editFileFlag = true;
                return true;
            }
            finally
            {
                Monitor.Exit(_editFileLock);
            }
        }

        private async void DeleteFile_Click(object sender, RoutedEventArgs e)
        {
            if (sender is Button button && button.CommandParameter is string fileId)
            {
                if (CanDeleteFile())
                {
                    //Confirm diaglog before delete
                    ContentDialog deleteDialog = new ContentDialog
                    {
                        Title = "Confirm Delete?",
                        Content = "Are you sure want delete this file?",
                        PrimaryButtonText = "Delete",
                        CloseButtonText = "Cancel"
                    };
                    deleteDialog.PrimaryButtonStyle = Application.Current.Resources["PrimaryDialogButton"] as Style;
                    deleteDialog.CloseButtonStyle = Application.Current.Resources["CloseDialogButton"] as Style;

                    var result = await deleteDialog.ShowAsync();
                    if (result == ContentDialogResult.Primary)
                    {
                        await DeleteFileAsync(fileId);
                    }
                    _deleteFileFlag = false;
                }
            }
        }

        private static readonly object _deleteFileLock = new object();
        private static bool _deleteFileFlag = false;
        private bool CanDeleteFile()
        {
            if (!Monitor.TryEnter(_deleteFileLock))
                return false;

            try
            {
                if (_deleteFileFlag)
                    return false;

                _deleteFileFlag = true;
                return true;
            }
            finally
            {
                Monitor.Exit(_deleteFileLock);
            }
        }

        private async Task DeleteFileAsync(string fileId)
        {
            using (var httpClient = HttpClientFactory.CreateClient(ClientNames.ApiClient))
            {
                try
                {
                    var response = await httpClient.DeleteAsync(Api.CdrFileById.FormatRoute(fileId));
                    if (response.IsSuccessStatusCode)
                    {
                        await ShowDialog("Delete Success", "File Deleted!");
                        await ViewModels.Reload();
                    }
                    else
                    {
                        await ShowDialog("Error!", "Cant delete file");
                    }
                }
                catch (Exception ex) when (!(ex is AppOutdatedException))
                {
                    await ShowDialog("Error!", $"Got exception: {ex.Message}");
                }
            }
        }


        private async Task ShowDialog(string title, string content)
        {
            ContentDialog dialog = new ContentDialog
            {
                Title = title,
                Content = content,
                CloseButtonText = "OK"
            };
            dialog.CloseButtonStyle = Application.Current.Resources["CloseDialogButton"] as Style;

            await dialog.ShowAsync();
        }

        private void btnFirst_Click(object sender, RoutedEventArgs e)
        {
            ViewModels.Pagination.Page = 1;
        }

        private void btnLast_Click(object sender, RoutedEventArgs e)
        {
            ViewModels.Pagination.Page = ViewModels.Pagination.TotalPage;
        }

        private void btnPrevious_Click(object sender, RoutedEventArgs e)
        {
            ViewModels.Pagination.Page--;
        }

        private void btnNext_Click(object sender, RoutedEventArgs e)
        {
            ViewModels.Pagination.Page++;
        }
    }
}
