using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Web.Models;
using System.Data.Entity.Migrations;
using AutomatizovanySklad.Core.Entity;
using static System.String;

namespace Web.Controllers {

  public class AccountController : BaseController {
    private ApplicationSignInManager _signInManager;
    private ApplicationUserManager applicationUserManager;

    public ApplicationSignInManager SignInManager
    {
      get
      {
        return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
      }
      private set
      {
        _signInManager = value;
      }
    }

    public ApplicationUserManager UserManager
    {
      get
      {
        return applicationUserManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
      }
      private set
      {
        _userManager = value;
      }
    }


    [AllowAnonymous]
    public ActionResult Login(string returnUrl) {
      ViewBag.ReturnUrl = returnUrl;
      return View();
    }

    [AllowAnonymous]
    public ActionResult AccessDenied() {
      return View();
    }

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) {

      if (!ModelState.IsValid) {
        return View(model);
      }
      var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);

      switch (result) {
        case SignInStatus.Success:
          AuthenticationManager.SignIn();
          Success("Přihlášení se provedlo úspěšně.", true);
          return RedirectToLocal(returnUrl);
     
        default:
          ModelState.AddModelError("", "Špatně zadané přihlašovací údaje");
          return View(model);
      }
    }

    [Authorize(Roles = "Vedouci")]
    public ActionResult Register() {
      var registrace = new RegisterViewModel();
      registrace.VybranyZamestnanec = databaze.Zamestnanci.Where(x=> x.Email != null && x.JeAktivni ).Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Jmeno + " " + x.Prijmeni });
      return View(registrace);
    }

    [Authorize(Roles = "Vedouci")]
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model) {
      if (ModelState.IsValid) {
        //pokud je modelState validní, kontrola jQuery
        //vytvoříme uživatele a Vytvoříme ho v UserManagerovi a ten vrácí výsledek do result
        var zamestnanec = databaze.Zamestnanci.First(z => z.Id == model.VybranyZamestnanecId);

        if (!IsNullOrEmpty(zamestnanec.Email)) {

          if (User.Identity.IsAuthenticated) {
            ApplicationUser uzivatel = _userManager.FindByNameAsync(User.Identity.Name).Result;
            //pokud je to vedoucí a registruje právě sebe odhlásí ho to
            if (zamestnanec.Email == uzivatel.Email) {
              AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
            }
            //Pokud již je registrován vymažu účet s heslem a vytvořím nový a přidám znovu roli
            var systemUser = _userManager.FindByEmail(zamestnanec.Email);
            if (systemUser != null) {
              _userManager.Delete(systemUser);
            }
            //Pokud je přihlášen zjistím kdo to je
          }
        }
        var user = new ApplicationUser { UserName = zamestnanec.Email, Email = zamestnanec.Email, VybranyZamestnanec = model.VybranyZamestnanecId };
        var result = await UserManager.CreateAsync(user, model.Password);
        //pokud je výsledek úspěšný načtu zamestnance a propojím s přihlášeným uživatelem
        if (result.Succeeded) {
          //podle typu zaměstnance přiradi role
          switch (zamestnanec.TypZamestnance) {
            case TypZamestnance.Vedouci:
              var userID = user.Id;
              result = UserManager.AddToRole(user.Id, "Vedouci");
              break;
            case TypZamestnance.Skladnik:
              result = UserManager.AddToRole(user.Id, "Skladnici");
              break;
            default:
              break;
          }
          databaze.Zamestnanci.AddOrUpdate(zamestnanec);
          databaze.SaveChanges();
          Success("Registrace byla úspěšná, teď stačí pouze přihlásit se!", true);
          return RedirectToAction("Index", "Home");
        }
        Danger("Heslo musí mít délku 6 znaků, obsahovat jeden velký a jeden speciální znak!",true);
      }
      model.VybranyZamestnanec = databaze.Zamestnanci.Where(x => x.Email != null).Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Jmeno + " " + x.Prijmeni });
      model.Title = "Registrace uživatele";
      return View(model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff() {
      AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
      return RedirectToAction("Index", "Home");
    }

    public ActionResult Odlasit(string zprava) {
      AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
      Danger(zprava, true);
      return RedirectToAction("Index", "Home");
    }

    protected override void Dispose(bool disposing) {
      if (disposing) {
        if (_signInManager != null) {
          _signInManager.Dispose();
          _signInManager = null;
        }
      }
      base.Dispose(disposing);
    }

    #region Helpers
    // Used for XSRF protection when adding external logins
    private const string XsrfKey = "XsrfId";

    private IAuthenticationManager AuthenticationManager
    {
      get
      {
        return HttpContext.GetOwinContext().Authentication;
      }
    }

    private void AddErrors(IdentityResult result) {
      foreach (var error in result.Errors) {
        ModelState.AddModelError("", error);
      }
    }

    private ActionResult RedirectToLocal(string returnUrl) {
      if (Url.IsLocalUrl(returnUrl)) {
        return Redirect(returnUrl);
      }
      return RedirectToAction("Index", "Home");
    }

    internal class ChallengeResult : HttpUnauthorizedResult {
      public ChallengeResult(string provider, string redirectUri)
          : this(provider, redirectUri, null) {
      }

      public ChallengeResult(string provider, string redirectUri, string userId) {
        LoginProvider = provider;
        RedirectUri = redirectUri;
        UserId = userId;
      }

      public string LoginProvider { get; set; }
      public string RedirectUri { get; set; }
      public string UserId { get; set; }

      public override void ExecuteResult(ControllerContext context) {
        var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
        if (UserId != null) {
          properties.Dictionary[XsrfKey] = UserId;
        }
        context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
      }
    }
    #endregion
  }
}