/*** 
@overview Life of German - Economy 
@author kookroach
@copyright (c) 2008 - 2019 Life of German 
*/


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GTANetworkAPI;
using Microsoft.EntityFrameworkCore;
using ReallifeGamemode.Database.Entities;
using ReallifeGamemode.Server.Extensions;
using ReallifeGamemode.Database.Models;
using ReallifeGamemode.Server.Services;

namespace ReallifeGamemode.Server.Finance
{
  public class Economy
  {
    public static Dictionary<int, Paycheck> Paychecks { get; set; } = new Dictionary<int, Paycheck>();

    public static (int, float, float) GetEconomyClass(Player client, int wage)
    {
      int bankAccount = client.GetUser().BankAccount.Balance;
      float financialHelp = -(float)Math.Pow(1.0005, -bankAccount) * -1000;
      float financialInterest = 1 - (float)Math.Pow(1.00006, -wage) * 1;
      if (financialInterest >= 0.7)
        financialInterest = 0.7f;

      if (financialHelp > 2500)
        financialHelp = 2500;

      return (bankAccount, financialHelp, financialInterest);
    }

    public static int GetVehicleTaxation(Player client)
    {
      int vehicleTaxation = 0;
      using (var dbContext = new DatabaseContext())
      {
        User user = client.GetUser(dbContext);
        foreach (UserVehicle uVeh in dbContext.UserVehicles.Where(u => u.UserId == user.Id))
        {
          if (uVeh.Price == null)
          {
            vehicleTaxation += 400;
            continue;
          }
          vehicleTaxation += (int)(uVeh.Price * 0.005f);
        }

      }
      return vehicleTaxation;
    }

    public static float GetPropertyTaxation(Player client)
    {
      float propertyTaxation = 0;
      User user = client.GetUser();
      if (user.HouseId != null)
      {
        propertyTaxation += user.House.Price * 0.005f;
      }

      return propertyTaxation;
    }


    public static void SetPaycheck(Player client, int wage)
    {
      (int bankAccount, float financialHelp, float financialInterest) = GetEconomyClass(client, wage);
      float propertyTax = GetPropertyTaxation(client);
      int vehicleTaxation = GetVehicleTaxation(client);
      int rentalFees = GetRentalFees(client);

      int amount = wage - (int)(wage * financialInterest) - vehicleTaxation - (int)propertyTax + (int)financialHelp - rentalFees;

      Paycheck paycheck = new Paycheck(financialHelp, financialInterest, vehicleTaxation, propertyTax, wage, amount, rentalFees);
      User user = client.GetUser();
      Paychecks[user.Id] = paycheck;
      ReleasePayDay(client, paycheck);
    }

    private static int GetRentalFees(Player client)
    {
      using (var dbContext = new DatabaseContext())
      {
        User user = client.GetUser();
        return dbContext.HouseRentals.Where(h => h.UserId == user.Id).Include(h => h.House).Sum(h => h.House.RentalFee);
      }
    }

    public static void ReleasePayDay(Player client, Paycheck paycheck)
    {
      using (var dbContext = new DatabaseContext())
      {
        client.GetUser(dbContext).BankAccount.Balance += paycheck.Amount;
        client.GetUser(dbContext).Wage = 0;
        dbContext.SaveChanges();
      }
      if (paycheck.Amount > 0)
        ChatService.SendMessage(client, "~g~[PAYDAY]~s~ Dein Stundenumsatz beträgt + $~g~" + paycheck.Amount + "~s~.");
      else
        ChatService.SendMessage(client, "~g~[PAYDAY]~s~ Dein Stundenumsatz beträgt - $~r~" + paycheck.Amount + "~s~.");

    }

    public static void PaydayTimer()
    {
      System.Timers.Timer timer = new System.Timers.Timer(60000);
      timer.Start();
      timer.Elapsed += Timer_Elapsed;
    }

    private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
      foreach (var player in NAPI.Pools.GetAllPlayers())
      {
        User user = player.GetUser();
        if (player.IsLoggedIn())
        {
          if (user.PaydayTimer <= 0)
          {
            Economy.SetPaycheck(player, user.Wage);
            using (var dbContext = new DatabaseContext())
            {
              player.GetUser(dbContext).PaydayTimer = 60;
              dbContext.SaveChanges();
            }
            return;
          }
          if (user.PaydayTimer > 0)
          {
            using (var dbContext = new DatabaseContext())
            {
              player.GetUser(dbContext).PaydayTimer -= 1;
              dbContext.SaveChanges();
            }
          }
        }
      }
    }
  }
}
