using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using ReactiveUI;
using TravelAroundRussia.Models;
using System.Text.RegularExpressions;
using System.Diagnostics;

namespace TravelAroundRussia.ViewModels
{
    /// <summary>
    /// Модель Главная страница Отелй, для просмотра всех отелей
    /// </summary>
	public class MainHotelPageViewModel : ReactiveObject
	{
        int cpage = 0;//индекс/номер страницы
        string countRecord = "10";//количество записей, отображаемых на странице [cтрока]
        int record = 10;//количество записей, отображаемых на странице [число]
        string countPage = "";//строка отображающая информацию о том сколько страниц и какая из них отображается
        //Изначальный список отелей [первые 10 записей]
        List<Hotel> hotelList = MainWindowViewModel.baseConnection.Hotels
            .Include(tb => tb.CountryCodeNavigation)
            .Take(10).ToList();
        /// <summary>
        /// Свойство Список отелей, который отрисовывает страницу занаво в случае изменения списка
        /// </summary>
        public List<Hotel> HotelList { get => hotelList; set => this.RaiseAndSetIfChanged(ref hotelList, value); }
        /// <summary>
        /// Свойство Информации о странице, который отрисовывает объект заново если новое значение отличается от предыдущего
        /// </summary>
        public string CountPage
        {
            get
            {
                //общее количество записей
                int count = MainWindowViewModel.baseConnection.Hotels.Count();
                //количество страниц
                //если остаток от деления общего числа записей на количество отображаемых записей > 0
                //добавляем еденицу к частному этих чисел, иначе берем частное
                count = (count % int.Parse(countRecord) != 0) ? (count / int.Parse(countRecord) + 1) : (count / int.Parse(countRecord));
                //возвращаем информацию об этом
                return "Страница " + (cpage + 1) + " из " + count;
            }
            set
            {
                //аналогично выше описаному
                int count = MainWindowViewModel.baseConnection.Hotels.Count();
                count = (count % int.Parse(countRecord) != 0) ? (count / int.Parse(countRecord) + 1) : (count / int.Parse(countRecord));
                string line = "Страница " + (cpage + 1) + " из " + count;
                //отрисовываем объект занаво
                this.RaiseAndSetIfChanged(ref countPage, line);
            }
        }
        /// <summary>
        /// Свойство Количество элементов на странице [n],
        /// который отрисовывает объект заново если новое значение отличается от предыдущего
        /// </summary>
        public string CountRecord 
        { 
            //передает количество элементов
            get => countRecord.ToString();
            set
            {                
                Regex r = new Regex("^\\d{1,}$");//регулярное выражение на проверку числа
                //если строка пустая, не проходит регулярное вырожение или равна 0 - ничего не происходит
                if (!string.IsNullOrWhiteSpace(value) && r.IsMatch(value) && value != "0")
                {
                    //старое значение, фиксирующе сколько элементов было отображено до этого
                    int oldcount = record * cpage;
                    try
                    {
                        //если количество записей > 0 - присваиваем введенное значение, иначе - 1
                        if (int.Parse(countRecord) > 0)
                            countRecord = value;
                        else
                            countRecord = "1";
                    }
                    catch(Exception ex) 
                    {
                        Debug.WriteLine(ex.Message);
                        //если что-то пошло не присваиваем дефолтное значение - 10
                        countRecord = "10";
                    }
                    finally
                    {
                        //если количество записей не равно 0 показываем заданное количество, иначе отображаем все
                        if (int.Parse(countRecord) != 0)
                        {
                            //считаем какая страница будет с учетом уже ранее пролистанных записей
                            cpage = oldcount / int.Parse(countRecord);
                            //находим необходимые записи и передаем в свойство
                            HotelList = MainWindowViewModel.baseConnection.Hotels.Include(tb => tb.CountryCodeNavigation).Skip(int.Parse(countRecord) * cpage).Take(int.Parse(countRecord)).ToList();
                            //изменяем строку информации 
                            CountPage = "";
                        }
                        else
                        {
                            //страница 1
                            cpage = 0;
                            //находим необходимые записи и передаем в свойство
                            HotelList = MainWindowViewModel.baseConnection.Hotels.Include(tb => tb.CountryCodeNavigation).ToList();
                            //изменяем строку информации 
                            CountPage = "";
                        }
                        //изменяем числовое значение о количестве записей
                        record = int.Parse(countRecord);
                    } 
                    //перерисовываем объект
                    this.RaiseAndSetIfChanged(ref countRecord, value);  
                }                              
            }
        }
        /// <summary>
        /// Свойство Количество записей, только на вывод
        /// </summary>
        public int CountAllRecord { get => MainWindowViewModel.baseConnection.Hotels.Count(); }
        /// <summary>
        /// Метод отображения самых первых n записей
        /// </summary>
        public void start()
        {
            //проверяем не отображается ли первая страница
            if (cpage != 0)
            {
                cpage = 0;//меняем странице на 1
                //показываем первые n записей
                HotelList = MainWindowViewModel.baseConnection.Hotels.Include(tb => tb.CountryCodeNavigation).Take(int.Parse(countRecord)).ToList();         
                CountPage = "";//изменяем строку информации о страницах
            }
        }
        /// <summary>
        /// Метод отображения самых последних записей
        /// </summary>
        public void end()
        {
            //общее количество записей
            int count = MainWindowViewModel.baseConnection.Hotels.Count();
            //количество страниц
            //если остаток от деления общего числа записей на количество отображаемых записей = 0
            //вычитаем еденицу от частного этих чисел, иначе берем частное
            count = (count % int.Parse(countRecord) != 0) ? (count / int.Parse(countRecord)) : (count / int.Parse(countRecord) - 1);
            //проверяем чтобы страница была не последней
            if (cpage != count)
            {
                cpage = count; ;//меняем страницу на последнюю
                //показываем остаток записей
                HotelList = MainWindowViewModel.baseConnection.Hotels.Include(tb => tb.CountryCodeNavigation).Skip(int.Parse(countRecord) * count).Take(int.Parse(countRecord)).ToList();
                CountPage = "";//изменяем строку информации о страницах
            }
        }
        /// <summary>
        /// Метод отображения следующих n записей
        /// </summary>
        public void next()
        {
            //общее количество записей
            int count = MainWindowViewModel.baseConnection.Hotels.Count();
            //количество страниц
            //если остаток от деления общего числа записей на количество отображаемых записей = 0
            //вычитаем еденицу от частного этих чисел, иначе берем частное
            count = (count % int.Parse(countRecord) != 0) ? (count / int.Parse(countRecord)) : (count / int.Parse(countRecord) - 1);
            //проверяем чтобы следущая страница была не больше последней
            if (cpage + 1! <= count)
            {
                cpage++;//переходим на следущую страницу
                //показываем n записей, пропустив необходимое количество записей
                HotelList = MainWindowViewModel.baseConnection.Hotels.Include(tb => tb.CountryCodeNavigation).Skip(int.Parse(countRecord) * cpage).Take(int.Parse(countRecord)).ToList();
                CountPage = "";//изменяем строку информации о страницах
            }

        }
        /// <summary>
        /// Метод отображенения предыдущих n записей
        /// </summary>
        public void back()
        {
            //если предыдущая страница не будет отрицательной
            if (cpage - 1 >= 0)
            {
                cpage--;//переходим на предыдущую страницу
                //показываем n записей
                HotelList = MainWindowViewModel.baseConnection.Hotels.Include(tb => tb.CountryCodeNavigation).Skip(int.Parse(countRecord) * cpage).Take(int.Parse(countRecord)).ToList();
                CountPage = "";//изменяем строку информации о страницах
            }
        }
    }
}