<commit_before>﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using Chart.Mvc.ComplexChart;
using Chart.Mvc.SimpleChart;
using ExpenseManager.BusinessLogic.DashboardServices.Models;
using ExpenseManager.Entity.Currencies;
using ExpenseManager.Entity.Providers;
using ExpenseManager.Entity.Providers.Queryable;
using ExpenseManager.Entity.Transactions;

namespace ExpenseManager.BusinessLogic.DashboardServices
{
    public class DashBoardService : ServiceWithWallet
    {
        private const int NumberOfTransactionsOnDashBoard = 5;
        private readonly ColorGeneratorService _colorGenerator;
        private readonly ITransactionsProvider _transactionsProvider;

        /// <summary>
        ///     Constructor with services and providers required by this service
        /// </summary>
        /// <param name="transactionsProvider"> provider with db access to transactions</param>
        /// <param name="colorGeneratorService">service which can generate colors</param>
        public DashBoardService(ITransactionsProvider transactionsProvider, ColorGeneratorService colorGeneratorService)
        {
            this._transactionsProvider = transactionsProvider;
            this._colorGenerator = colorGeneratorService;
        }

        #region protected

        protected override IWalletsQueryable WalletsProvider
        {
            get { return this._transactionsProvider; }
        }

        #endregion

        /// <summary>
        ///     Will return just transaction which can be seen by this user
        /// </summary>
        /// <param name="userId"> id of logged user</param>
        /// <returns> queryable for accessible transactions</returns>
        public IQueryable<Transaction> GetAccessibleResults(Guid userId)
        {
            return
                this._transactionsProvider.Transactions
                    .Where(t =>
                        (t.Wallet.WalletAccessRights.Any(war => war.UserProfile.Guid == userId) ||
                         t.Budget.AccessRights.Any(bar => bar.UserProfile.Guid == userId))
                    );
        }

        /// <summary>
        ///     provides list of wallets available for user
        /// </summary>
        /// <param name="userId"> user with access to provided wallets</param>
        /// <returns>select item for front end</returns>
        public async Task<List<SelectListItem>> GetAccessibleWallets(Guid userId)
        {
            return await
                this._transactionsProvider.Wallets.Where(
                    w => w.WalletAccessRights.Any(war => war.UserProfile.Guid == userId)).Select(w => new SelectListItem
                    {
                        Value = w.Guid.ToString(),
                        Text = w.Name
                    }).ToListAsync();
        }

        /// <summary>
        ///     Generate wrapper values using categories
        /// </summary>
        /// <param name="collection"></param>
        /// <returns> non negative values for all categories</returns>
        public async Task<List<SimpleGraphModel>> GetWrapperValuesForCategories(IQueryable<Transaction> collection)
        {
            return await collection
                .GroupBy(t => t.Category.Name)
                .Select(
                    x =>
                        new SimpleGraphModel
                        {
                            Label = x.Key,
                            Value = x.Sum(f => Math.Abs(f.Amount))
                        })
                .ToListAsync();
        }

        /// <summary>
        ///     Returns graph data for months in last year
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public async Task<GraphWithDescriptionModel> GetGraphForMonthLastYear(IQueryable<Transaction> collection)
        {
            var result = await
                collection.GroupBy(t => new {t.Date.Month, t.Date.Year}).Select(
                    x =>
                        new SimpleGraphModel
                        {
                            Label = x.Key.Month + ". " + x.Key.Year,
                            Value = x.Sum(f => f.Amount)
                        })
                    .ToListAsync();
            return new GraphWithDescriptionModel {Description = "Last year report", GraphData = result};
        }

        /// <summary>
        ///     Returns graph data for days in last month
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public async Task<GraphWithDescriptionModel> GetGraphForDaysLastMonth(IQueryable<Transaction> collection)
        {
            var result = await
                collection.GroupBy(t => new {t.Date.Day, t.Date.Month}).Select(
                    x =>
                        new SimpleGraphModel
                        {
                            Label = x.Key.Day + ". " + x.Key.Month + ".",
                            Value = x.Sum(f => f.Amount)
                        })
                    .ToListAsync();
            return new GraphWithDescriptionModel {Description = "Last Month Report", GraphData = result};
        }

        /// <summary>
        ///     Filter transactions using filter
        /// </summary>
        /// <param name="mappedFilter"> filter to be used</param>
        /// <param name="userId">guid of logged user profile</param>
        /// <returns>DashBoardServiceModel filled with graphs transactions and so on</returns>
        public async Task<DashBoardServiceModel> GenerateDataForFilter(FilterDataServiceModel mappedFilter, Guid userId)
        {
            // select transactions according to filter
            var userWallet = await this.GetWalletById(userId);
            var resultMonth = this.FilterTransactions(mappedFilter.WithMonthFilterValues(), userId, userWallet.Currency);
            var resultYear = this.FilterTransactions(mappedFilter.WithYearFilterValues(), userId, userWallet.Currency);
            // prepare data for graphs
            var categoriesExpense =
                await this.GetWrapperValuesForCategories(resultMonth.Where(t => t.Amount < 0));
            var categoriesIncome =
                await this.GetWrapperValuesForCategories(resultMonth.Where(t => t.Amount >= 0));
            var monthSummary = await this.GetGraphForDaysLastMonth(resultMonth);
            var yearSummary = await this.GetGraphForMonthLastYear(resultYear);
            // generate charts
            return new DashBoardServiceModel
            {
                CategoriesExpenseChart = this.GeneratePieChart(categoriesExpense),
                CategoriesIncomeChart = this.GeneratePieChart(categoriesIncome),
                MonthSummaryChart = this.GenerateLineChart(monthSummary),
                YearSummaryChart = this.GenerateLineChart(yearSummary),
                Transactions = await this.LastTransactions(userId)
            };
        }

        #region private

        /// <summary>
        ///     Filter transactions using filter
        /// </summary>
        /// <param name="filter"> filter to be used</param>
        /// <param name="currentUser">guid of logged user profile</param>
        /// ///<commit_msg>[#71] Refactor of home controller fix<commit_after>﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;
using Chart.Mvc.ComplexChart;
using Chart.Mvc.SimpleChart;
using ExpenseManager.BusinessLogic.DashboardServices.Models;
using ExpenseManager.Entity.Currencies;
using ExpenseManager.Entity.Providers;
using ExpenseManager.Entity.Providers.Queryable;
using ExpenseManager.Entity.Transactions;

namespace ExpenseManager.BusinessLogic.DashboardServices
{
    public class DashBoardService : ServiceWithWallet
    {
        private const int NumberOfTransactionsOnDashBoard = 5;
        private readonly ColorGeneratorService _colorGenerator;
        private readonly ITransactionsProvider _transactionsProvider;

        /// <summary>
        ///     Constructor with services and providers required by this service
        /// </summary>
        /// <param name="transactionsProvider"> provider with db access to transactions</param>
        /// <param name="colorGeneratorService">service which can generate colors</param>
        public DashBoardService(ITransactionsProvider transactionsProvider, ColorGeneratorService colorGeneratorService)
        {
            this._transactionsProvider = transactionsProvider;
            this._colorGenerator = colorGeneratorService;
        }

        #region protected

        protected override IWalletsQueryable WalletsProvider
        {
            get { return this._transactionsProvider; }
        }

        #endregion

        /// <summary>
        ///     Will return just transaction which can be seen by this user
        /// </summary>
        /// <param name="userId"> id of logged user</param>
        /// <returns> queryable for accessible transactions</returns>
        public IQueryable<Transaction> GetAccessibleResults(Guid userId)
        {
            return
                this._transactionsProvider.Transactions
                    .Where(t =>
                        (t.Wallet.WalletAccessRights.Any(war => war.UserProfile.Guid == userId) ||
                         t.Budget.AccessRights.Any(bar => bar.UserProfile.Guid == userId))
                    );
        }

        /// <summary>
        ///     provides list of wallets available for user
        /// </summary>
        /// <param name="userId"> user with access to provided wallets</param>
        /// <returns>select item for front end</returns>
        public async Task<List<SelectListItem>> GetAccessibleWallets(Guid userId)
        {
            return await
                this._transactionsProvider.Wallets.Where(
                    w => w.WalletAccessRights.Any(war => war.UserProfile.Guid == userId)).Select(w => new SelectListItem
                    {
                        Value = w.Guid.ToString(),
                        Text = w.Name
                    }).ToListAsync();
        }

        /// <summary>
        ///     Generate wrapper values using categories
        /// </summary>
        /// <param name="collection"></param>
        /// <returns> non negative values for all categories</returns>
        public async Task<List<SimpleGraphModel>> GetWrapperValuesForCategories(IQueryable<Transaction> collection)
        {
            return await collection
                .GroupBy(t => t.Category.Name)
                .Select(
                    x =>
                        new SimpleGraphModel
                        {
                            Label = x.Key,
                            Value = x.Sum(f => Math.Abs(f.Amount))
                        })
                .ToListAsync();
        }

        /// <summary>
        ///     Returns graph data for months in last year
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public async Task<GraphWithDescriptionModel> GetGraphForMonthLastYear(IQueryable<Transaction> collection)
        {
            var result = await
                collection.GroupBy(t => new {t.Date.Month, t.Date.Year}).Select(
                    x =>
                        new SimpleGraphModel
                        {
                            Label = x.Key.Month + ". " + x.Key.Year,
                            Value = x.Sum(f => f.Amount)
                        })
                    .ToListAsync();
            return new GraphWithDescriptionModel {Description = "Last year report", GraphData = result};
        }

        /// <summary>
        ///     Returns graph data for days in last month
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public async Task<GraphWithDescriptionModel> GetGraphForDaysLastMonth(IQueryable<Transaction> collection)
        {
            var result = await
                collection.GroupBy(t => new {t.Date.Day, t.Date.Month}).Select(
                    x =>
                        new SimpleGraphModel
                        {
                            Label = x.Key.Day + ". " + x.Key.Month + ".",
                            Value = x.Sum(f => f.Amount)
                        })
                    .ToListAsync();
            return new GraphWithDescriptionModel {Description = "Last Month Report", GraphData = result};
        }

        /// <summary>
        ///     Filter transactions using filter
        /// </summary>
        /// <param name="mappedFilter"> filter to be used</param>
        /// <param name="userId">guid of logged user profile</param>
        /// <returns>DashBoardServiceModel filled with graphs transactions and so on</returns>
        public async Task<DashBoardServiceModel> GenerateDataForFilter(FilterDataServiceModel mappedFilter, Guid userId)
        {
            // select transactions according to filter
            var userWallet = await this.GetWalletByUserId(userId);
            var resultMonth = this.FilterTransactions(mappedFilter.WithMonthFilterValues(), userId, userWallet.Currency);
            var resultYear = this.FilterTransactions(mappedFilter.WithYearFilterValues(), userId, userWallet.Currency);
            // prepare data for graphs
            var categoriesExpense =
                await this.GetWrapperValuesForCategories(resultMonth.Where(t => t.Amount < 0));
            var categoriesIncome =
                await this.GetWrapperValuesForCategories(resultMonth.Where(t => t.Amount >= 0));
            var monthSummary = await this.GetGraphForDaysLastMonth(resultMonth);
            var yearSummary = await this.GetGraphForMonthLastYear(resultYear);
            // generate charts
            return new DashBoardServiceModel
            {
                CategoriesExpenseChart = this.GeneratePieChart(categoriesExpense),
                CategoriesIncomeChart = this.GeneratePieChart(categoriesIncome),
                MonthSummaryChart = this.GenerateLineChart(monthSummary),
                YearSummaryChart = this.GenerateLineChart(yearSummary),
                Transactions = await this.LastTransactions(userId)
            };
        }

        #region private

        /// <summary>
        ///     Filter transactions using filter
        /// </summary>
        /// <param name="filter"> filter to be used</param>
        /// <param name="currentUser">guid of logged user profile</param>
        /// ///
{'fraction_non_alphanumeric': 0.09643734643734644, 'fraction_numerical': 0.000546000546000546, 'mean_word_length': 1.7889227255424438, 'pattern_counts': {'":': 0, '<': 127, '<?xml version=': 0, '>': 161, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1092546', 'n_tokens_mistral': 3448, 'n_tokens_neox': 3375, 'n_words': 811}