using PCUT.Models;
using System;
using System.Collections.Generic;
using System.Timers;
using PCUT.Extensions;

namespace PCUT.ViewModels
{
    public class PaginationViewModel : NotificationBase, IDisposable
    {
        private const string PageSizeKey = "PCUT_list_pagesize";
        private const int DefaultPageSize = 20;

        public event PageChangedEventHandler PageChanged;
        public event TextSearchedEventHandler TextSearched;

        private readonly Timer _timer;

        public PaginationViewModel(bool withSearch = false)
        {
            if (withSearch)
            {
                _timer = new Timer(500);
                _timer.AutoReset = false;
                _timer.Enabled = true;
                _timer.Elapsed += (sender, args) => {
                    TextSearched?.Invoke(this, new TextSearchEventArgs(SearchText));
                };
                _timer.Stop();
            }
            _pageSize = GetPageSize();
            PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == nameof(Page) || args.PropertyName == nameof(PageSize))
                {
                    PageChanged?.Invoke(this, new PageChangedEventArgs(Page, PageSize));
                }
            };
        }

        public List<int> AvailablePageSizes { get; } = new List<int> { 20, 50, 100, 200 };

        private string _searchText;
        public string SearchText
        {
            get => _searchText;
            set
            {
                if (_searchText != value)
                {
                    _searchText = value;
                    RaisePropertyChanged(nameof(SearchText));
                    _timer.Stop();
                    _timer.Start();
                }
            }
        }

        public void InitSearchText(string text)
        {
            if (_searchText != text)
            {
                _searchText = text;
                RaisePropertyChanged(nameof(SearchText));
            }
        }

        private int _page = 0;
        public int Page
        {
            get { return _page; }
            set
            {
                if (_page != value && value > 0 && value <= _totalPage)
                    SetProperty(ref _page, value);
            }
        }

        private int _pageSize;
        public int PageSize
        {
            get { return _pageSize; }
            set
            {
                SetProperty(ref _pageSize, value);
                SetPageSize(value);
            }
        }

        private int _totalPage = 1;
        public int TotalPage
        {
            get { return _totalPage; }
            set { SetProperty(ref _totalPage, value); }

        }

        private int _totalRecords = 0;
        public int TotalRecords
        {
            get { return _totalRecords; }
            set { SetProperty(ref _totalRecords, value); }
        }

        public void Dispose()
        {
            _timer?.Dispose();
        }

        private static int GetPageSize()
        {
            var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
            if (localSettings.TryGetValue<int>(PageSizeKey, out var value))
                return value;
            else
                return DefaultPageSize;
        }

        private static void SetPageSize(int pageSize)
        {
            var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
            localSettings.Values[PageSizeKey] = pageSize;
        }
    }

    public delegate void TextSearchedEventHandler(object sender, TextSearchEventArgs args);
    public class TextSearchEventArgs : EventArgs
    {
        public string Text { get; }
        public TextSearchEventArgs(string text)
        {
            Text = text;
        }
    }

    public delegate void PageChangedEventHandler(object sender, PageChangedEventArgs args);
    public class PageChangedEventArgs : EventArgs
    {
        public int Page { get; }
        public int PageSize { get; }

        public PageChangedEventArgs(int page, int pageSize)
        {
            Page = page;
            PageSize = pageSize;
        }
    }
}
