using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Web;
using System.Web.Mvc;
using AutomatizovanySklad.Core;
using AutomatizovanySklad.Core.Entity;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Web.Models;
using Web.Models.DodaciList;
using Web.Models.Karta;
using Web.Models.Karta.Produkt;
using Web.Models.Subjekt;
using Web.Models.Zamestnanec;
using WebGrease.Css.Extensions;
using static System.String;

namespace Web.Controllers {
  public abstract class BaseController : Controller {

    protected AppDbContext databaze;
    protected UserStore<ApplicationUser> _store;
    protected UserManager<ApplicationUser> _userManager;

    public BaseController() {
      databaze = new AppDbContext();
      _store = new UserStore<ApplicationUser>(new ApplicationDbContext());
      _userManager = new UserManager<ApplicationUser>(_store);
    }

    protected override void Dispose(bool disposing) {
      base.Dispose(disposing);
      databaze.Dispose();
      _store.Dispose();
      _userManager.Dispose();
    }

    protected virtual TModel PridejDatumVytvoreni<TModel>(TModel entita) where TModel : ITrackableEntity {
      entita.DatumVytvoreni = DateTime.UtcNow;
      entita.DatumUpravy = DateTime.UtcNow;
      ApplicationUser uzivatel = _userManager.FindByNameAsync(User.Identity.Name).Result;
      entita.VytvorilId = uzivatel.VybranyZamestnanec;
      entita.UpravilId = uzivatel.VybranyZamestnanec;
      return entita;
    }

    protected virtual TModel PridejDatumZmeny<TModel>(TModel entita) where TModel : ITrackableEntity {
      entita.DatumVytvoreni = entita.DatumVytvoreni;
      entita.DatumUpravy = DateTime.UtcNow;
      ApplicationUser uzivatel = _userManager.FindByNameAsync(User.Identity.Name).Result;
      entita.VytvorilId = entita.VytvorilId;
      entita.UpravilId = uzivatel.VybranyZamestnanec;
      return entita;
    }

    protected virtual void ZmenTypZamestnance(TypZamestnance typZamestnance, string email) {
      var user = _userManager.FindByEmail(email);

      //Pokud uživatel je registrován v IS změní mu to roli
      if (user != null) {
        //Vymazat jeho role 
        _userManager.RemoveFromRole(user.Id, "Vedouci");
        _userManager.RemoveFromRole(user.Id, "Skladnici");
        switch (typZamestnance) {
          case TypZamestnance.Vedouci:
            _userManager.AddToRole(user.Id, "Vedouci");
            break;
          case TypZamestnance.Skladnik:
            _userManager.AddToRole(user.Id, "Skladnici");
            break;
          default:
            break;
        }
      }
    }

    protected virtual void DeaktivujEmailZamestnance(string email) {
      var user = _userManager.FindByEmail(email);

      //Pokud uživatel je registrován v IS změní mu to roli
      if (user != null) {
        //Vymazat jeho email 
        user.Email = null;
        _userManager.Update(user);
      }
    }

    #region Alert

    public void Success(string message, bool dismissable = false) {
      AddAlert(AlertStyles.Success, message, dismissable);
    }

    public void Information(string message, bool dismissable = false) {
      AddAlert(AlertStyles.Information, message, dismissable);
    }

    public void Warning(string message, bool dismissable = false) {
      AddAlert(AlertStyles.Warning, message, dismissable);
    }

    public void Danger(string message, bool dismissable = false) {
      AddAlert(AlertStyles.Danger, message, dismissable);
    }

    private void AddAlert(string alertStyle, string message, bool dismissable) {
      var alerts = TempData.ContainsKey(Alert.TempDataKey)
          ? (List<Alert>)TempData[Alert.TempDataKey]
          : new List<Alert>();

      alerts.Add(new Alert {
        AlertStyle = alertStyle,
        Message = message,
        Dismissable = dismissable
      });

      TempData[Alert.TempDataKey] = alerts;
    }

    #endregion

    #region Mapper

    #region Zamestnanec
 

    protected virtual ZamestnanecModel EntitaToZamestnanec(Zamestnanec zamestnanec) {
      var zamestnanecModel = new ZamestnanecModel();
      zamestnanecModel.Jmeno = zamestnanec.Jmeno;
      zamestnanecModel.Email = zamestnanec.Email;
      zamestnanecModel.Id = zamestnanec.Id;
      zamestnanecModel.Poznamka = zamestnanec.Poznamka;
      zamestnanecModel.Prijmeni = zamestnanec.Prijmeni;
      zamestnanecModel.TypZamestnance = zamestnanec.TypZamestnance;
      zamestnanecModel.CeleJmeno = $"{zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      zamestnanecModel.DatumUpravy = zamestnanec.DatumUpravy;
      zamestnanecModel.DatumVytvoreni = zamestnanec.DatumVytvoreni;
      zamestnanecModel.UpravilId = zamestnanec.UpravilId;
      zamestnanecModel.VytvorilId = zamestnanec.VytvorilId;
      if (zamestnanec.VytvorilId != zamestnanec.UpravilId) {
        var zamestnanecModifikace = databaze.Zamestnanci.First(z => z.Id == zamestnanec.UpravilId);

        zamestnanecModel.InfoOModifikaci = $"{VratLokalniCas(zamestnanec.DatumUpravy.ToString())} - {zamestnanecModifikace.Jmeno} {zamestnanecModifikace.Prijmeni}";
      } else {
        var zamestnanecModifikace = databaze.Zamestnanci.First(z => z.Id == zamestnanec.VytvorilId);
        zamestnanecModel.InfoOModifikaci = $"{VratLokalniCas(zamestnanec.DatumVytvoreni.ToString())} - {zamestnanecModifikace.Jmeno} {zamestnanecModifikace.Prijmeni}";
      }
      return zamestnanecModel;
    }

    protected virtual ZamestnanecEditModel EntitaToZamestnanecEdit(Zamestnanec zamestnanec) {
      var zamestnanecModel = new ZamestnanecEditModel();
      zamestnanecModel.Jmeno = zamestnanec.Jmeno;
      zamestnanecModel.Email = zamestnanec.Email;
      zamestnanecModel.Id = zamestnanec.Id;
      zamestnanecModel.Poznamka = zamestnanec.Poznamka;
      zamestnanecModel.Prijmeni = zamestnanec.Prijmeni;
      zamestnanecModel.TypZamestnance = zamestnanec.TypZamestnance;
      zamestnanecModel.CeleJmeno = $"{zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      zamestnanecModel.DatumUpravy = zamestnanec.DatumUpravy;
      zamestnanecModel.DatumVytvoreni = zamestnanec.DatumVytvoreni;
      zamestnanecModel.UpravilId = zamestnanec.UpravilId;
      zamestnanecModel.VytvorilId = zamestnanec.VytvorilId;
      if (zamestnanec.VytvorilId != zamestnanec.UpravilId) {
        var zamestnanecModifikace = databaze.Zamestnanci.First(z => z.Id == zamestnanec.UpravilId);
        zamestnanecModel.InfoOModifikaci = $"{VratLokalniCas(zamestnanec.DatumUpravy.ToString())} - {zamestnanecModifikace.Jmeno} {zamestnanecModifikace.Prijmeni}";
      } else {
        var zamestnanecModifikace = databaze.Zamestnanci.First(z => z.Id == zamestnanec.VytvorilId);
        zamestnanecModel.InfoOModifikaci = $"{VratLokalniCas(zamestnanec.DatumVytvoreni.ToString())} - {zamestnanecModifikace.Jmeno} {zamestnanecModifikace.Prijmeni}";
      }
      return zamestnanecModel;
    }

    protected virtual Zamestnanec ZamestnanecToEntita(ZamestnanecModel zamestnanecModel) {
      var zamestnanec = new Zamestnanec();
      zamestnanec.Id = zamestnanecModel.Id;
      zamestnanec.Jmeno = zamestnanecModel.Jmeno;
      zamestnanec.Email = zamestnanecModel.Email;
      zamestnanec.Poznamka = zamestnanecModel.Poznamka;
      zamestnanec.Prijmeni = zamestnanecModel.Prijmeni;
      zamestnanec.TypZamestnance = zamestnanecModel.TypZamestnance;
      zamestnanec.DatumUpravy = zamestnanecModel.DatumUpravy;
      zamestnanec.DatumVytvoreni = zamestnanecModel.DatumVytvoreni;
      zamestnanec.UpravilId = zamestnanecModel.UpravilId;
      zamestnanec.VytvorilId = zamestnanecModel.VytvorilId;
      return zamestnanec;
    }

    protected virtual Zamestnanec ZamestnanecEditToEntita(ZamestnanecEditModel zamestnanecModel) {
      var zamestnanec = new Zamestnanec();
      zamestnanec.Id = zamestnanecModel.Id;
      zamestnanec.Jmeno = zamestnanecModel.Jmeno;
      zamestnanec.Email = zamestnanecModel.Email;
      zamestnanec.Poznamka = zamestnanecModel.Poznamka;
      zamestnanec.Prijmeni = zamestnanecModel.Prijmeni;
      zamestnanec.TypZamestnance = zamestnanecModel.TypZamestnance;
      zamestnanec.DatumUpravy = zamestnanecModel.DatumUpravy;
      zamestnanec.DatumVytvoreni = zamestnanecModel.DatumVytvoreni;
      zamestnanec.UpravilId = zamestnanecModel.UpravilId;
      zamestnanec.VytvorilId = zamestnanecModel.VytvorilId;
      return zamestnanec;
    }

    #endregion

    #region Subjekt
    protected virtual SubjektModel EntitaToSubjekt(Subjekt subjekt) {
      var subjektModel = new SubjektModel();
      subjektModel.Adresa = subjekt.Adresa;
      subjektModel.Jmeno = subjekt.Jmeno;
      subjektModel.DIC = subjekt.DIC;
      subjektModel.ICO = subjekt.ICO;
      subjektModel.Id = subjekt.Id;
      subjektModel.Poznamka = subjekt.Poznamka;
      subjektModel.TypSubjektu = subjekt.TypSubjektu;
      subjektModel.Kontakt = subjekt.Kontakt;
      subjektModel.DatumUpravy = subjekt.DatumUpravy;
      subjektModel.DatumVytvoreni = subjekt.DatumVytvoreni;
      subjektModel.UpravilId = subjekt.UpravilId;
      subjektModel.VytvorilId = subjekt.VytvorilId;
      if (subjekt.VytvorilId != subjekt.UpravilId) {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == subjekt.UpravilId);
        subjektModel.InfoOModifikaci = $"{VratLokalniCas(subjekt.DatumUpravy.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      } else {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == subjekt.VytvorilId);
        subjektModel.InfoOModifikaci = $"{VratLokalniCas(subjekt.DatumVytvoreni.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      }
      return subjektModel;
    }

    protected virtual Subjekt SubjektToEntita(SubjektModel subjektModel) {
      var subjekt = new Subjekt();
      subjekt.Adresa = subjektModel.Adresa;
      subjekt.Jmeno = subjektModel.Jmeno;
      subjekt.DIC = subjektModel.DIC;
      subjekt.ICO = subjektModel.ICO;
      subjekt.Poznamka = subjektModel.Poznamka;
      subjekt.TypSubjektu = subjektModel.TypSubjektu;
      subjekt.Kontakt = subjektModel.Kontakt;
      subjekt.DatumUpravy = subjektModel.DatumUpravy;
      subjekt.DatumVytvoreni = subjektModel.DatumVytvoreni;
      subjekt.UpravilId = subjektModel.UpravilId;
      subjekt.VytvorilId = subjektModel.VytvorilId;
      subjekt.Id = subjektModel.Id;
      return subjekt;
    }

    #endregion 

    #region Karta

    protected virtual KartaModel EntitaToKarta(Karta karta) {
      var kartaModel = new KartaModel();
      kartaModel.Nazev = karta.Nazev;
      kartaModel.Id = karta.Id;
      kartaModel.MaxPocet = karta.MaxPocet;
      kartaModel.MernaJednotka = karta.MernaJednotka;
      int pocet = 0;
      karta.SeznamProduktu.ForEach(k => {
        kartaModel.SeznamProduktu.Add(EntitaToProdukt(k));
        if (k.TypTransakce == TypTransakce.Prodej) { pocet -= k.Pocet; } else {
          pocet += k.Pocet;
        }
      });
      // Pokaždé vypočítat
      kartaModel.Pocet = pocet;
      //karta.SeznamSubjektu.ForEach(k => kartaModel.SeznamSubjektu.Add(EntitaToSubjekt(k)));
      kartaModel.PocetZMaxima = $"{pocet}/{kartaModel.MaxPocet}";
      kartaModel.DatumUpravy = karta.DatumUpravy;
      kartaModel.DatumVytvoreni = karta.DatumVytvoreni;
      kartaModel.UpravilId = karta.UpravilId;
      kartaModel.VytvorilId = karta.VytvorilId;
      if (karta.VytvorilId != karta.UpravilId) {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == karta.UpravilId);
        kartaModel.InfoOModifikaci = $"{VratLokalniCas(karta.DatumUpravy.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      } else {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == karta.VytvorilId);
        kartaModel.InfoOModifikaci = $"{VratLokalniCas(karta.DatumVytvoreni.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      }
      return kartaModel;
    }

    protected virtual KartaEditModel EntitaToKartaEdit(Karta karta) {
      var kartaModel = new KartaEditModel();
      kartaModel.Nazev = karta.Nazev;
      kartaModel.Id = karta.Id;
      kartaModel.MaxPocet = karta.MaxPocet;
      kartaModel.Pocet = karta.Pocet;
      kartaModel.MernaJednotka = karta.MernaJednotka;
      double pocet = 0;
      karta.SeznamProduktu.ForEach(k => {
        kartaModel.SeznamProduktu.Add(EntitaToProdukt(k));
        if (k.TypTransakce == TypTransakce.Prodej) { pocet -= k.Pocet; } else {
          pocet += k.Pocet;
        }
      });
      //karta.SeznamSubjektu.ForEach(k => kartaModel.SeznamSubjektu.Add(EntitaToSubjekt(k)));
      kartaModel.PocetZMaxima = $"{pocet}/{kartaModel.MaxPocet}";
      kartaModel.DatumUpravy = karta.DatumUpravy;
      kartaModel.DatumVytvoreni = karta.DatumVytvoreni;
      kartaModel.UpravilId = karta.UpravilId;
      kartaModel.VytvorilId = karta.VytvorilId;
      if (karta.VytvorilId != karta.UpravilId) {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == karta.UpravilId);
        kartaModel.InfoOModifikaci = $"{VratLokalniCas(karta.DatumUpravy.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      } else {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == karta.VytvorilId);
        kartaModel.InfoOModifikaci = $"{VratLokalniCas(karta.DatumVytvoreni.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      }
      return kartaModel;
    }

    protected virtual Karta KartaToEntita(KartaModel kartaModel) {
      var karta = new Karta();
      karta.Nazev = kartaModel.Nazev;
      karta.MaxPocet = kartaModel.MaxPocet;
      karta.Pocet = kartaModel.Pocet ?? 0;
      kartaModel.SeznamProduktu.ForEach(k => karta.SeznamProduktu.Add(ProduktToEntita(k)));
      //kartaModel.SeznamSubjektu.ForEach(k => karta.SeznamSubjektu.Add(SubjektToEntita(k)));
      karta.DatumUpravy = kartaModel.DatumUpravy;
      karta.DatumVytvoreni = kartaModel.DatumVytvoreni;
      karta.UpravilId = kartaModel.UpravilId;
      karta.VytvorilId = kartaModel.VytvorilId;
      karta.Id = kartaModel.Id;
      karta.MernaJednotka = kartaModel.MernaJednotka;
      return karta;
    }

    protected virtual Karta KartaEditToEntita(KartaEditModel kartaModel) {
      var karta = new Karta();
      karta.Nazev = kartaModel.Nazev;
      karta.MaxPocet = kartaModel.MaxPocet;
      karta.Pocet = kartaModel.Pocet ?? 0;
      kartaModel.SeznamProduktu.ForEach(k => karta.SeznamProduktu.Add(ProduktToEntita(k)));
     // kartaModel.SeznamSubjektu.ForEach(k => karta.SeznamSubjektu.Add(SubjektToEntita(k)));
      karta.DatumUpravy = kartaModel.DatumUpravy;
      karta.DatumVytvoreni = kartaModel.DatumVytvoreni;
      karta.UpravilId = kartaModel.UpravilId;
      karta.VytvorilId = kartaModel.VytvorilId;
      karta.Id = kartaModel.Id;
      karta.MernaJednotka = kartaModel.MernaJednotka;
      return karta;
    }

    #endregion

    #region Produkt
    protected virtual ProduktModel EntitaToProdukt(Produkt produkt) {
      var produktModel = new ProduktModel();
      databaze.DodaciListy.ForEach(d => {
        if (d.SeznamProduktu.Any(p => p.Id == produkt.Id)) {
          produktModel.JeVDodacimListu = true;
        }
      });

      produktModel.Id = produkt.Id;
      produktModel.Cena = produkt.Cena;
      produktModel.Kod = produkt.Kod;
      produktModel.CenaCelkem = produkt.Cena * produkt.Pocet;
      produktModel.TypTransakce = produkt.TypTransakce;
      produktModel.Pocet = produkt.Pocet;
      produktModel.DatumUpravy = produkt.DatumUpravy;
      produktModel.DatumVytvoreni = produkt.DatumVytvoreni;
      produktModel.UpravilId = produkt.UpravilId;
      produktModel.VytvorilId = produkt.VytvorilId;

      if (produkt.VytvorilId != produkt.UpravilId) {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == produkt.UpravilId);
        produktModel.InfoOModifikaci = $"{VratLokalniCas(produkt.DatumUpravy.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      } else {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == produkt.VytvorilId);
        produktModel.InfoOModifikaci = $"{VratLokalniCas(produkt.DatumVytvoreni.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      }
      produktModel.SouborEntita = produkt.Soubor;
      return produktModel;
    }

    protected virtual Produkt ProduktToEntita(ProduktModel produktModel) {
      var produkt = new Produkt();
      produkt.Cena = produktModel.Cena;
      produkt.Kod = produktModel.Kod;
      produkt.Pocet = produktModel.Pocet;
      produkt.TypTransakce = produktModel.TypTransakce;
      produkt.DatumUpravy = produktModel.DatumUpravy;
      produkt.DatumVytvoreni = produktModel.DatumVytvoreni;
      produkt.UpravilId = produktModel.UpravilId;
      produkt.VytvorilId = produktModel.VytvorilId;
      produkt.Id = produktModel.Id;
      return produkt;
    }

    #endregion

    #region DodaciList
    protected virtual DodaciListModel EntitaToDodaciList(DodaciList dodaciList) {
      var dodaciListModel = new DodaciListModel();
      var produkty = new List<Produkt>();
      var soubory = new List<Soubor>();

      dodaciListModel.Id = dodaciList.Id;

      dodaciListModel.DatumUpravy = dodaciList.DatumUpravy;
      dodaciListModel.DatumVytvoreni = dodaciList.DatumVytvoreni;
      dodaciListModel.UpravilId = dodaciList.UpravilId;
      dodaciListModel.VytvorilId = dodaciList.VytvorilId;

      //Vytažení produktů
      databaze.DodaciListy.Where(d => d.Id == dodaciList.Id).ForEach(d => d.SeznamProduktu.ForEach(p => produkty.Add(p)));
      // Vytažení souborů
      databaze.DodaciListy.Where(d => d.Id == dodaciList.Id).ForEach(d => d.Soubory.ForEach(s => soubory.Add(s)));
      //Přidání produktů
      produkty.ForEach(p => {
        var zaznam = new DodaciListZaznamModel();
        zaznam.ProduktModel = EntitaToProdukt(p);
        dodaciListModel.Zaznamy.Add(zaznam);
      });
      //Přidání souborů
      dodaciListModel.Soubory = soubory;
      dodaciListModel.KodDodacihoListu = dodaciList.KodDodacihoListu;
      dodaciListModel.TypTransakce = dodaciList.TypTransakce;
      //Cena produktu
      dodaciList.SeznamProduktu.ForEach(p => dodaciListModel.CelkovaCena += p.Cena * p.Pocet);
      dodaciListModel.Id = dodaciList.Id;
      //dodaciList.Soubory.ForEach(d => dodaciListModel.Soubory.Add(d));
      //Vybere subjekt pokud existuje
      var firstOrDefault = databaze.Subjekty.FirstOrDefault(s => s.Id == dodaciList.Subjekt.Id);
      if (firstOrDefault != null)
        dodaciListModel.Subjekt = EntitaToSubjekt(firstOrDefault);
      if (dodaciList.VytvorilId != dodaciList.UpravilId) {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == dodaciList.UpravilId);
        dodaciListModel.InfoOModifikaci = $"{VratLokalniCas(dodaciList.DatumUpravy.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      } else {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == dodaciList.VytvorilId);
        dodaciListModel.InfoOModifikaci = $"{VratLokalniCas(dodaciList.DatumVytvoreni.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      }

      return dodaciListModel;
    }

    protected virtual DodaciListEditModel EntitaToDodaciListEdit(DodaciList dodaciList) {
      var dodaciListModel = new DodaciListEditModel();
      var produkty = new List<Produkt>();
      var soubory = new List<Soubor>();

      dodaciListModel.Id = dodaciList.Id;

      dodaciListModel.DatumUpravy = dodaciList.DatumUpravy;
      dodaciListModel.DatumVytvoreni = dodaciList.DatumVytvoreni;
      dodaciListModel.UpravilId = dodaciList.UpravilId;
      dodaciListModel.VytvorilId = dodaciList.VytvorilId;

      //Vytažení produktů
      databaze.DodaciListy.Where(d => d.Id == dodaciList.Id).ForEach(d => d.SeznamProduktu.ForEach(p => produkty.Add(p)));
      // Vytažení souborů
      databaze.DodaciListy.Where(d => d.Id == dodaciList.Id).ForEach(d => d.Soubory.ForEach(s => soubory.Add(s)));
      //Přidání produktů
      produkty.ForEach(p => {
        var zaznam = new DodaciListZaznamModel();
        zaznam.ProduktModel = EntitaToProdukt(p);
        dodaciListModel.Zaznamy.Add(zaznam);
      });
      //Přidání souborů
      dodaciListModel.Soubory = soubory;
      dodaciListModel.KodDodacihoListu = dodaciList.KodDodacihoListu;
      dodaciListModel.TypTransakce = dodaciList.TypTransakce;
      //Cena produktu
      dodaciList.SeznamProduktu.ForEach(p => dodaciListModel.CelkovaCena += p.Cena * p.Pocet);
      dodaciListModel.Id = dodaciList.Id;
      //dodaciList.Soubory.ForEach(d => dodaciListModel.Soubory.Add(d));
      //Vybere subjekt pokud existuje
      var firstOrDefault = databaze.Subjekty.FirstOrDefault(s => s.Id == dodaciList.Subjekt.Id);
      if (firstOrDefault != null)
        dodaciListModel.Subjekt = EntitaToSubjekt(firstOrDefault);
      if (dodaciList.VytvorilId != dodaciList.UpravilId) {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == dodaciList.UpravilId);
        dodaciListModel.InfoOModifikaci = $"{VratLokalniCas(dodaciList.DatumUpravy.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      } else {
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == dodaciList.VytvorilId);
        dodaciListModel.InfoOModifikaci = $"{VratLokalniCas(dodaciList.DatumVytvoreni.ToString())} - {zamestnanec.Jmeno} {zamestnanec.Prijmeni}";
      }

      return dodaciListModel;
    }

    protected virtual DodaciList DodaciListToEntita(DodaciListModel dodaciListModel) {
      var dodaciList = new DodaciList();
      dodaciList.Id = dodaciListModel.Id;
      dodaciList.DatumUpravy = dodaciListModel.DatumUpravy;
      dodaciList.DatumVytvoreni = dodaciListModel.DatumVytvoreni;
      dodaciList.UpravilId = dodaciListModel.UpravilId;
      dodaciList.VytvorilId = dodaciListModel.VytvorilId;
      dodaciList.TypTransakce = dodaciListModel.TypTransakce;
      dodaciList.KodDodacihoListu = dodaciListModel.KodDodacihoListu;
      dodaciList.Subjekt = databaze.Subjekty.Include(nameof(Adresa)).Include(nameof(Kontakt))
        .FirstOrDefault(s => s.Id == dodaciListModel.VybranySubjektId);
      return dodaciList;
    }

    protected virtual DodaciList DodaciListEditToEntita(DodaciListEditModel dodaciListModel) {
      var dodaciList = new DodaciList();
      dodaciList.Id = dodaciListModel.Id;
      dodaciList.DatumUpravy = dodaciListModel.DatumUpravy;
      dodaciList.DatumVytvoreni = dodaciListModel.DatumVytvoreni;
      dodaciList.UpravilId = dodaciListModel.UpravilId;
      dodaciList.VytvorilId = dodaciListModel.VytvorilId;
      dodaciList.TypTransakce = dodaciListModel.TypTransakce;
      dodaciList.KodDodacihoListu = dodaciListModel.KodDodacihoListu;
      dodaciList.Subjekt = databaze.Subjekty.Include(nameof(Adresa)).Include(nameof(Kontakt))
        .FirstOrDefault(s => s.Id == dodaciListModel.VybranySubjektId);
      return dodaciList;
    }
    #endregion

    #endregion

    protected void ZkontrolujStavZboziAUpozorni(Karta karta) {
      if (karta.Pocet >= karta.MaxPocet) {
        var zamestnanci = databaze.Zamestnanci.Where(z => z.TypZamestnance == TypZamestnance.Vedouci).ToList();
        zamestnanci.ForEach(z => { if (!IsNullOrEmpty(z.Email)) { OdesliEmail("Přetížení skladu u skladové karty " + karta.Nazev + " !", "dobesstavbysro@seznam.cz", "Systém", z.Email, "Skladové zásoby", "Heslo123*", null); } });
      } else if (karta.Pocet <= ((double)karta.MaxPocet / 100) * 20) {
        var zamestnanci = databaze.Zamestnanci.Where(z => z.TypZamestnance == TypZamestnance.Vedouci).ToList();
        zamestnanci.ForEach(z => { if (!IsNullOrEmpty(z.Email)) { OdesliEmail("Malé zásoby u skladové karty " + karta.Nazev + " !", "dobesstavbysro@seznam.cz", "Systém", z.Email, "Skladové zásoby", "Heslo123*", null); } });
      }
    }

    protected void OdesliEmail(string zprava, string odEmail, string odJmeno, 
      string komuEmail, string predmet, string heslo, HttpPostedFileBase fileUploader) {
      var body = "<p>Email od: {0} ({1})</p><p>Zpráva:</p><p>{2}</p>";
      var message = new MailMessage();
      message.To.Add(new MailAddress(komuEmail));
      message.From = new MailAddress(odEmail);
      message.Subject = predmet;
      zprava = IsNullOrEmpty(zprava) ? "0" : zprava;
      message.Body = Format(body, odJmeno, odEmail, zprava);
      message.IsBodyHtml = true;
      if (fileUploader != null) {
        string fileName = Path.GetFileName(fileUploader.FileName);
        message.Attachments.Add(new Attachment(fileUploader.InputStream, fileName));
      }
      try {
        using (var smtp = new SmtpClient()) {
          var credential = new NetworkCredential {
            UserName = odEmail,
            Password = heslo
          };
          smtp.Credentials = credential;
          smtp.Host = "smtp.seznam.cz";
          smtp.Port = 587;
          smtp.EnableSsl = true;
          smtp.Send(message);
        }
      } catch (Exception e) {
        Danger("Chyba internetu: " + e);
      }
    }

    protected bool JeKorektniPridavaniProduktu(Produkt produkt, Karta karta) {
      if (produkt.TypTransakce == TypTransakce.Nákup) {
        if ((karta.Pocet + produkt.Pocet) <= ((double)karta.MaxPocet / 100) * 120) {
          karta.Pocet += produkt.Pocet;
          return true;
        }
      } else {
        if (karta.Pocet - produkt.Pocet >= 0) {
          karta.Pocet -= produkt.Pocet;
          return true;
        }
      }
      return false;
    }

    protected bool JeKorektniEditovaniProduktu(Produkt produkt, Karta karta) {
      //Kontrola zda je typtransakce změněna
      var staryProdukt = databaze.Produkty.FirstOrDefault(p => p.Id == produkt.Id);

      if (produkt.TypTransakce != staryProdukt.TypTransakce) {
        if (produkt.TypTransakce == TypTransakce.Nákup) {
          //Pokud je typ transakce nákup tak předtím prodával a musí se starý typ + a nový typ také
          if ((karta.Pocet + staryProdukt.Pocet + produkt.Pocet) <= ((double)karta.MaxPocet / 100) * 120) {
            karta.Pocet = karta.Pocet + staryProdukt.Pocet + produkt.Pocet;
            return true;
          }
        } else {
          if (karta.Pocet - staryProdukt.Pocet - produkt.Pocet >= 0) {
            karta.Pocet = karta.Pocet - staryProdukt.Pocet - produkt.Pocet;
            return true;
          }
        }
      } else {
        if (produkt.TypTransakce == TypTransakce.Nákup) {
          if ((karta.Pocet - staryProdukt.Pocet + produkt.Pocet) <= ((double)karta.MaxPocet / 100) * 120) {
            karta.Pocet = karta.Pocet - staryProdukt.Pocet + produkt.Pocet;
            return true;
          }
        } else {
          if (karta.Pocet + staryProdukt.Pocet - produkt.Pocet >= 0) {
            karta.Pocet = karta.Pocet + staryProdukt.Pocet - produkt.Pocet;
            return true;
          }
        }
      }
      return false;
    }

    //Pri odebirani delam opak pridavnai
    protected bool JeKorektniOdebiraniProduktu(Produkt produkt, Karta karta) {
      if (produkt.TypTransakce == TypTransakce.Nákup) {
        if ((karta.Pocet - produkt.Pocet) >= 0) {
          karta.Pocet -= produkt.Pocet;
          return true;
        }
      } else {
        if (karta.Pocet + produkt.Pocet <= ((double)karta.MaxPocet / 100) * 120) {
          karta.Pocet += produkt.Pocet;
          return true;
        }
      }
      return false;
    }

    protected bool JeKorektniPridavaniProduktu(Produkt produkt, Karta karta, TypTransakce typTransakce) {
      //Pokud prodam je to příjem ...
      if (typTransakce == TypTransakce.Nákup) {
        if ((karta.Pocet + produkt.Pocet) <= ((double)karta.MaxPocet / 100) * 120) {
          karta.Pocet += produkt.Pocet;
          produkt.TypTransakce = TypTransakce.Nákup;
          return true;
        }
      } else {
        if ((karta.Pocet - produkt.Pocet) >= 0) {
          karta.Pocet -= produkt.Pocet;
          produkt.TypTransakce = TypTransakce.Prodej;
          return true;
        }
      }
      return false;
    }

    private DateTime VratLokalniCas(string datum) {
      DateTime konvertovaneDatum = DateTime.SpecifyKind(
        DateTime.Parse(datum),
        DateTimeKind.Utc);
      DateTime dt = konvertovaneDatum.ToLocalTime();

      return dt;
    }
  }

}