using System;
using System.Threading.Tasks;
using DotVVM.Framework.ViewModel;
using DotVVM.Framework.Runtime.Filters;
using ElectroShop.Services;
using ElectroShop.Models;
using System.Collections.Generic;
using DotVVM.Framework.Controls;
using DotVVM.Framework.Storage;
using System.Linq;
using System.IO;
using ElectroShop.Resources;
using DotVVM.BusinessPack.Controls;
using DotVVM.Framework.Hosting;
using System.Text;

namespace ElectroShop.ViewModels
{
    public class ElectronicComponentManagementViewModel : MasterPageViewModel
    {
        private readonly ElectronicComponentService electronicComponentService;
        private readonly IUploadedFileStorage fileStorage;
        private readonly CathegoryService cathegoryService;

        public ElectronicComponentManagementViewModel(ElectronicComponentService electronicComponentService,
            IUploadedFileStorage fileStorage, CathegoryService cathegoryService)
        {
            this.electronicComponentService = electronicComponentService;
            this.fileStorage = fileStorage;
            this.cathegoryService = cathegoryService;
        }

        [Bind(Direction.ServerToClient)]
        public GridViewDataSet<ElectronicComponentModel> ElectronicComponents { get; set; }

        /// <summary>
        /// Klic je ID komponenty, hodnota - cislo komponenty v objednavce
        /// </summary>
        public Dictionary<int, int> OrderCount { get; set; }

        public List<OrderItem> OrderItems { get; set; }

        public string FilterByName { get; set; }
        public List<string> Cathegories { get; set; }
        public string SelectedCathegory { get; set; }
        public bool IsModalDisplayed { get; set; }

        private GridViewDataSetLoadedData<ElectronicComponentModel> GetData(IGridViewDataSetLoadOptions gridViewDataSetLoadOptions)
        {
            //  Povoli Pagign and Sorting.
            var query = electronicComponentService.GetAllQueriable();
            if (FilterByName != null && FilterByName != "")
            {
                query = query.Where(x => x.Name.StartsWith(FilterByName));
            }

            if (SelectedCathegory != null && SelectedCathegory != "")
            {
                query = query.Where(x => x.ElectronicComponentCategory.Name == SelectedCathegory);
            }

            return query.GetDataFromQueryable(gridViewDataSetLoadOptions);
        }


        public override Task Init()
        {
            OrderItems = new List<OrderItem>();
            OrderCount = new Dictionary<int, int>();
            Cathegories = cathegoryService.GetAllCategoriesNames();
            ElectronicComponents = GridViewDataSet.Create(gridViewDataSetLoadDelegate: GetData, pageSize: 10);
            return base.Init();
        }

        public async Task AddToOrder(int componentId)
        {
            ElectronicComponentModel m = electronicComponentService.GetById(componentId);

            if (OrderCount.ContainsKey(componentId))
            {
                if (OrderCount[componentId] != m.NumberAvailable)
                {
                    OrderCount[componentId] = OrderCount[componentId] + 1;
                }
            }
            else
            {
                if (m.NumberAvailable != 0)
                {
                    OrderCount.Add(componentId, 1);
                }
            }
            CreateOrderItemsListAccordingToActualState();
        }

        public void RemoveOneItemFromOrder(int componentId)
        {
            if (OrderCount.ContainsKey(componentId))
            {
                if (OrderCount[componentId] == 0)
                {
                    OrderCount[componentId] = 0;
                }
                else
                {
                    OrderCount[componentId] = OrderCount[componentId] - 1;
                }
                CreateOrderItemsListAccordingToActualState();
            }
        }


        private void SetAllOrderCountsToZero()
        {
            foreach (var key in OrderCount.Keys.ToList())
            {
                OrderCount[key] = 0;
            }
        }

        public void GenerateOrder()
        {
            try
            {
                CreateOrderItemsListAccordingToActualState();
                var now = DateTime.Now;
                StringBuilder sb = new StringBuilder();
                string seperator = "\t\t|\t\t";
                string lineSeparator = System.Environment.NewLine;
                string headerSeparator =
                    lineSeparator +
                    "----------------------------------------------------------------------------------------------------"
                    + lineSeparator;

                sb.Append(Texts.Name + seperator + Texts.Cathegory + seperator + Texts.Number);
                sb.Append(headerSeparator);
                foreach (var item in OrderItems)
                {
                    sb.Append(item.Item.Name + seperator + item.Item.ElectronicComponentCategory.Name
                        + seperator + item.Count +
                        lineSeparator);
                }

                sb.Append(lineSeparator);
                sb.Append(lineSeparator);
                sb.Append(lineSeparator);

                sb.Append(Texts.GeneratedAtTime + now.Day.ToString() + "/" + now.Month.ToString() + " " +
                       now.Year.ToString() + " " + now.Hour.ToString() + ":" + now.Minute.ToString() + ".");

                using (var stream = GenerateStreamFromString(sb.ToString()))
                {
                    Context.ReturnFile(stream, Texts.Order + "_" +
                       now.Day.ToString() + "_" +
                       now.Month.ToString() + "_" +
                       now.Year.ToString() + "_" +
                       now.Hour.ToString() + "_" +
                       now.Minute.ToString()
                       + ".txt", "text/plain");
                }
            }
            finally
            {
                IsModalDisplayed = true;
            }
        }

        public void CloseModal()
        {
            OrderItems = new List<OrderItem>();
            OrderCount = new Dictionary<int, int>();
            ElectronicComponents = GridViewDataSet.Create(gridViewDataSetLoadDelegate: GetData, pageSize: 10);
        }

        public void AcceptAndCloseOrder()
        {
            CreateOrderItemsListAccordingToActualState();
            foreach (var item in OrderItems)
            {
                var itemTmp = item.Item;
                itemTmp.NumberAvailable = item.Item.NumberAvailable - item.Count;
                electronicComponentService.Update(itemTmp);
            }
            ElectronicComponents = GridViewDataSet.Create(gridViewDataSetLoadDelegate: GetData, pageSize: 10);
            SetAllOrderCountsToZero();
            CreateOrderItemsListAccordingToActualState();
            IsModalDisplayed = false;
        }

        public void ShowOrder()
        {
            CreateOrderItemsListAccordingToActualState();
            IsModalDisplayed = true;
        }

        private void CreateOrderItemsListAccordingToActualState()
        {
            OrderItems = new List<OrderItem>() { };
            foreach (var item in OrderCount)
            {
                if (item.Value > 0)
                {
                    ElectronicComponentModel m = electronicComponentService.GetById(item.Key);
                    OrderItems.Add(new OrderItem() { Item = m, Count = item.Value });
                }
            }
        }

        private static Stream GenerateStreamFromString(string s)
        {
            var stream = new MemoryStream();
            var writer = new StreamWriter(stream);
            writer.Write(s);
            writer.Flush();
            stream.Position = 0;
            return stream;
        }

        public void FilterEnter()
        {
            ElectronicComponents = GridViewDataSet.Create(gridViewDataSetLoadDelegate: GetData, pageSize: 10);
        }

        public void DownloadDatasheet(Guid fileId, string name)
        {
            if (fileId != null)
            {
                using (var stream = fileStorage.GetFile(fileId))
                {
                    Context.ReturnFile(stream, "Datasheet_" + name + ".pdf", "application/pdf");
                }
            }
        }
    }
}
