using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using RedSocial;

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using RedSocial.Models;

namespace RedSocial.Controllers
{
    public class UsersController : Controller
    {
        private Entities db = new Entities();

        /******************** USER ********************/

        // GET: Menu Partial
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult LeftMenuPartial()
        {
            var id = User.Identity.GetUserId();
            AspNetUser user = db.AspNetUsers.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }
            return View(user);
        }

        // GET: Users with filter
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult SearchByUserName(string userName)
        {
            //recuperar usuario actual
            var user_id = User.Identity.GetUserId();
            AspNetUser user = db.AspNetUsers.Find(user_id);
            if (user == null)
            {
                return HttpNotFound();
            }
            //recuperar los usuarios que coinciden con la busqueda
            var aspNetUsers = db.AspNetUsers.Include(a => a.Sex);

            var results = from c in aspNetUsers
                          where c.UserName.Contains(userName)
                          select c;
            FriendsViewModel model = new FriendsViewModel();
            model.myFriends = user.AspNetUsers;
            model.otherUsers = results.ToList();
            return View("Friends", model);
        }

        // GET: Users/Profile/id
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult Profile(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            AspNetUser aspNetUser = db.AspNetUsers.Find(id);
            if (aspNetUser == null)
            {
                return HttpNotFound();
            }
            //ordenar los posts
            var posts_ordered = aspNetUser.Posts.OrderByDescending(x => x.DateTime).ToList();
            aspNetUser.Posts = posts_ordered;
            return View(aspNetUser);
        }

        // GET: Users/MyProfile
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult MyProfile()
        {
            var id = User.Identity.GetUserId();
            AspNetUser user = db.AspNetUsers.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }
            ViewBag.SexId = new SelectList(db.Sexes, "Id", "Name", user.SexId);
            return View(user);
        }

        // GET: Users/Posts/5
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult Posts(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            AspNetUser user = db.AspNetUsers.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }
            var posts = user.Posts;
            return View(posts.ToList());
        }

        // GET: Users/Friends
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult Friends()
        {
            var id = User.Identity.GetUserId();
            AspNetUser user = db.AspNetUsers.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }
            FriendsViewModel model = new FriendsViewModel();
            model.myFriends = user.AspNetUsers;
            model.otherUsers = user.AspNetUsers;

            return View("Friends", model);
        }

        // GET: Users/AddFriend/5
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult AddFriend(string id)
        {
            //recuperar usuario actual
            var user_id = User.Identity.GetUserId();
            AspNetUser user = db.AspNetUsers.Find(user_id);
            if (user == null)
            {
                return HttpNotFound();
            }
            //recuperar amigo
            var friend = db.AspNetUsers.Find(id);
            //agregar amigo
            user.AspNetUsers.Add(friend);
            db.SaveChanges();
            //redirigir a la vista
            FriendsViewModel model = new FriendsViewModel();
            model.myFriends = user.AspNetUsers;
            model.otherUsers = user.AspNetUsers;
            return View("Friends", model);
        }

        // GET: Users/RemoveFriend/5
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult RemoveFriend(string id)
        {
            //recuperar usuario actual
            var user_id = User.Identity.GetUserId();
            AspNetUser user = db.AspNetUsers.Find(user_id);
            if (user == null)
            {
                return HttpNotFound();
            }
            //recuperar amigo
            var friend = db.AspNetUsers.Find(id);
            //eliminar amigo
            user.AspNetUsers.Remove(friend);
            db.SaveChanges();
            //eliminar conversacion y mensajes con el amigo
            var conversations = db.Conversations.Where(x =>
             x.UserIdTo == user.Id && x.UserIdFrom == friend.Id
             ||
             x.UserIdTo == friend.Id && x.UserIdFrom == user.Id
            ).ToList();
            foreach (var c in conversations)
            {
                db.Conversations.Remove(c);
                db.SaveChanges();
            }
            //redirigir a la vista
            FriendsViewModel model = new FriendsViewModel();
            model.myFriends = user.AspNetUsers;
            model.otherUsers = user.AspNetUsers;
            return View("Friends", model);
        }

        // POST: Users/Edit/5
        // Para protegerse de ataques de publicación excesiva, habilite las propiedades específicas a las que desea enlazarse. Para obtener 
        // más información vea http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult EditMyProfile([Bind(Include = "Id,Email,EmailConfirmed,PasswordHash,SecurityStamp,PhoneNumber,PhoneNumberConfirmed,TwoFactorEnabled,LockoutEndDateUtc,LockoutEnabled,AccessFailedCount,UserName,SexId,LiveIn,Web,FullName,ImgPrincipal,ImgProfile")] AspNetUser aspNetUser)
        {
            if (ModelState.IsValid)
            {
                db.Entry(aspNetUser).State = EntityState.Modified;
                db.SaveChanges();

            }
            ViewBag.SexId = new SelectList(db.Sexes, "Id", "Name", aspNetUser.SexId);
            return View("MyProfile", aspNetUser);
        }

        [HttpPost]
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult UploadImageProfile(HttpPostedFileBase file)
        {
            //recuperar al usuario actual
            var id = User.Identity.GetUserId();
            AspNetUser user = db.AspNetUsers.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }
            //subir imagen
            string ruta = Upload.UploadImage(file, GlobalConstants.RouteProfileImages, this.Server);
            //actualizar en bbdd
            user.ImgProfile = ruta;
            db.SaveChanges();
            //volver a la vista
            return RedirectToAction("MyProfile");
        }

        [HttpPost]
        [Authorize(Roles = GlobalConstants.RoleUser)]
        public ActionResult UploadImagePrincipal(HttpPostedFileBase file)
        {
            //recuperar al usuario actual
            var id = User.Identity.GetUserId();
            AspNetUser user = db.AspNetUsers.Find(id);
            if (user == null)
            {
                return HttpNotFound();
            }
            //subir imagen
            string ruta = Upload.UploadImage(file, GlobalConstants.RoutePrincipalImages, this.Server);
            //actualizar en bbdd
            user.ImgPrincipal = ruta;
            db.SaveChanges();
            //volver a la vista
            return RedirectToAction("MyProfile");
        }


        /******************** ADMIN ********************/

        // GET: Users
        [Authorize(Roles = GlobalConstants.RoleAdmin)]
        public ActionResult Index()
        {
            var aspNetUsers = db.AspNetUsers.Include(a => a.Sex);
            return View(aspNetUsers.ToList());
        }

        // GET: Users/Create
        [Authorize(Roles = GlobalConstants.RoleAdmin)]
        public ActionResult Create()
        {
            ViewBag.SexId = new SelectList(db.Sexes, "Id", "Name");
            ViewBag.AspNetRoles = db.AspNetRoles;
            return View();
        }

        // POST: Users/Create
        // Para protegerse de ataques de publicación excesiva, habilite las propiedades específicas a las que desea enlazarse. Para obtener 
        // más información vea http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = GlobalConstants.RoleAdmin)]
        public async System.Threading.Tasks.Task<ActionResult> Create(RegisterAdminViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser
                {
                    UserName = model.UserName,
                    Email = model.Email,
                    FullName = model.FullName,
                    Web = model.Web,
                    LiveIn = model.LiveIn,
                    ImgProfile = GlobalConstants.RouteImgProfile,
                    ImgPrincipal = GlobalConstants.RouteImgPrincipal,
                };
                var UserManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
                var result = await UserManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    var currentUser = UserManager.FindByName(user.UserName);

                    foreach (string r in model.AspNetRoles) {
                        AspNetRole rol = db.AspNetRoles.Find(r);
                        var roleresult = UserManager.AddToRole(currentUser.Id, rol.Name);
                    }
                }
                    return RedirectToAction("Index");
            }

            ViewBag.SexId = new SelectList(db.Sexes, "Id", "Name", model.SexId);
            ViewBag.AspNetRoles = db.AspNetRoles;
            return View(model);
        }

        // GET: Users/Edit/5
        [Authorize(Roles = GlobalConstants.RoleAdmin)]
        public ActionResult Edit(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            AspNetUser aspNetUser = db.AspNetUsers.Find(id);
            if (aspNetUser == null)
            {
                return HttpNotFound();
            }
            ViewBag.SexId = new SelectList(db.Sexes, "Id", "Name", aspNetUser.SexId);
            return View(aspNetUser);
        }

        // POST: Users/Edit/5
        // Para protegerse de ataques de publicación excesiva, habilite las propiedades específicas a las que desea enlazarse. Para obtener 
        // más información vea http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = GlobalConstants.RoleAdmin)]
        public ActionResult Edit([Bind(Include = "Id,Email,UserName,SexId,LiveIn,Web,FullName,ImgPrincipal,ImgProfile")] AspNetUser aspNetUser)
        {
            if (ModelState.IsValid)
            {
                db.Entry(aspNetUser).State = EntityState.Modified;
                db.SaveChanges();

            }
            ViewBag.SexId = new SelectList(db.Sexes, "Id", "Name", aspNetUser.SexId);
            return View(aspNetUser);
        }

        // GET: Users/Delete/5
        [Authorize(Roles = GlobalConstants.RoleAdmin)]
        public ActionResult Delete(string id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            AspNetUser aspNetUser = db.AspNetUsers.Find(id);
            if (aspNetUser == null)
            {
                return HttpNotFound();
            }
            return View(aspNetUser);
        }

        // POST: Users/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = GlobalConstants.RoleAdmin)]
        public ActionResult DeleteConfirmed(string id)
        {
            AspNetUser aspNetUser = db.AspNetUsers.Find(id);
            db.AspNetUsers.Remove(aspNetUser);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }

    }
}
