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 ResourcesManager.Models;
using Microsoft.AspNet.Identity;
using ResourcesManager.ViewModels;
using System.IO;
using System.Text;
using System.Drawing;
using System.Web.Helpers;
using System.Net.Mime;
using Microsoft.AspNet.SignalR;
using ResourcesManager.Helpers;
using ResourcesManager.Interfaces;
using ResourcesManager.Handlers;
using ResourcesManager.Repositories;

namespace ResourcesManager.Controllers
{
    [System.Web.Mvc.Authorize]
    public class ResourcesController : Controller
    {
        ApplicationDbContext context;
        private IResourceRepository resourceRepo;
        private IUserRepository userRepo;
        private IStatisticRepository statisticRepo;
        readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public ResourcesController()
        {
            context = new ApplicationDbContext();
            resourceRepo = new ResourceRepository(context);
            userRepo = new UserRepository(context);
            statisticRepo = new StatisticRepository(context);
        }

        public ResourcesController(IResourceRepository resouceRepo)
        {
            this.resourceRepo = resouceRepo;
        }

        public ResourcesController(IResourceRepository resouceRepo, IUserRepository userRepo)
        {
            this.resourceRepo = resouceRepo;
            this.userRepo = userRepo;
        }
        public ResourcesController(IResourceRepository resouceRepo, IUserRepository userRepo, IStatisticRepository statisticRepository)
        {
            this.resourceRepo = resouceRepo;
            this.userRepo = userRepo;
            this.statisticRepo = statisticRepository;
        }

        public ActionResult GetImage(string path)
        {
            try
            {
                return File(path, "image");
            }
            catch (Exception ex)
            {
                log.Error("", ex);
                return null;
            }
        }

        private void pictureDelete(string path)
        {
            try
            {
                if (System.IO.File.Exists(path))
                {
                    System.IO.File.Delete(path);
                }
            }
            catch (Exception e)
            {
                log.Error("Request Url: " + Request.Url + " Path: " + path, e);
                throw new HttpException("PictureDelete Error!");
            }

        }

        private Resource pictureUploadTo(Resource resource)
        {       
            try
            {
                var stream = Request.Files[0].InputStream;
                string path;

                if (stream.Length != 0)
                {
                    var img = new WebImage(stream);
                    string fileName = Path.GetRandomFileName();
                    fileName = Path.ChangeExtension(fileName, img.ImageFormat);
                    path = Path.Combine(Server.MapPath("~/App_Data/ResourceImages/"), fileName);

                    if (img.Width > 128)
                    {
                        img.Resize(129, 129, true).Crop(1, 1);
                    }
                    try
                    {
                        img.Save(path);
                    }
                    catch (Exception e)
                    {
                        log.Error("Image Save", e);
                        throw new HttpException("ImageUpload Hiba!");
                    }


                    resource.ImagePath = "~/App_Data/ResourceImages/" + fileName;
                }
                else
                {
                    resource.ImagePath = "~/App_Data/ResourceImages/DefaultResource.png";
                }
                stream.Flush();
                stream.Close();

                return resource;
            }
            catch (Exception ex)
            {
                log.Error("", ex);
                return null;
            }
        }

        public ActionResult Index()
        {
            return View(resourceRepo.GetResouces());
        }

        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                log.Warn("BadRequest");
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Resource resource = resourceRepo.GetResourceByID((int)id);
            if (resource == null)
            {
                log.Warn("HttpNotFound");
                return HttpNotFound();
            }
            return View(resource);
        }

        [System.Web.Mvc.Authorize(Roles = "Admin")]
        public ActionResult Create()
        {
            return View();
        }

        [System.Web.Mvc.Authorize(Roles = "Admin")]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "AssetTag,Name,IsShared,TimeLimit,Description,ImagePath,Reservation,Users")]Resource resource)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    if (resourceRepo.GetResouces().Any(m => m.AssetTag == resource.AssetTag))
                    {
                        ModelState.AddModelError("AssetTag", "Ilyen már létezik");
                        return View(resource);
                    }
                    if (resource.TimeLimit < 1)
                    {
                        ModelState.AddModelError("TimeLimit", "Nem lehet negatív");
                        return View(resource);
                    }

                    try
                    {
                        resource.Users = userRepo.GetUsers().ToList();
                        resourceRepo.InsertResouce(pictureUploadTo(resource));
                        statisticRepo.InsertStatistic(new StatisticModel()
                        {
                            ResourceId = resource.Id,
                            UserId = User.Identity.GetUserId(),
                            StatisticType = StatisticType.ResourceCreate,
                            DateTime = DateTime.Now
                        });
                    }
                    catch (Exception e)
                    {
                        log.Error("DB Hiba!", e);
                        return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
                    }

                    var allUser =  userRepo.GetUsers().Select(k => k.UserName).ToList();
                    string message = string.Format("{0} létrehozta {1} erőforrást.", User?.Identity?.Name, resource.Name);
                    string url = "/Resources/Details/" + resource.Id;
                    NotificationHelper.Send(allUser, "Új erőforrás", message, resource.ImagePath, url);
                }
                catch (Exception ex)
                {
                    log.Error("", ex);
                    return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
                }

                return RedirectToAction("Index");
            }

            return View(resource);
        }

        [System.Web.Mvc.Authorize(Roles = "Admin")]
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                log.Warn("BadRequest");
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Resource resource = resourceRepo.GetResourceByID((int)id);
            if (resource == null)
            {
                log.Warn("HttpNotFound");
                return HttpNotFound();
            }
            return View(resource);
        }

        [System.Web.Mvc.Authorize(Roles = "Admin")]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(Resource resource)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    //Leltári azonosító ellenőrzés
                    var model = resourceRepo.GetResourceByID(resource.Id);
                    var resources = resourceRepo.GetResouces().ToList();
                    foreach (var item in resources)
                    {
                        if (resource.AssetTag == item.AssetTag && (resource.AssetTag != model.AssetTag))
                        {
                            ModelState.AddModelError("AssetTag", "Ilyen már létezik");
                            return View(model);
                        }
                    }
                    //Kép feltöltés ellenörzése
                    var stream = Request?.Files[0]?.InputStream;
                    string oldPath = resourceRepo.GetResourceByID(resource.Id).ImagePath;
                    string path;
                    if (stream != null && stream.Length != 0)
                    {
                        //Kép mentése
                        var image = new WebImage(stream);
                        string fileName = Path.GetRandomFileName();
                        fileName = Path.ChangeExtension(fileName, image.ImageFormat);
                        path = Path.Combine(Server.MapPath("~/App_Data/ResourceImages/"), fileName);
                        if (image.Width > 128)
                        {
                            image.Resize(129, 129, true).Crop(1, 1);
                        }
                        image.Save(path);
                        log.Info("ImageSaved: " + path);
                        //Előző kép törlése
                        model.ImagePath = "~/App_Data/ResourceImages/" + fileName;
                        if (Path.GetFileName(oldPath) != "DefaultResource.png")
                        {
                            pictureDelete(Server.MapPath(oldPath));
                        }
                        log.Info("PictureDeleted: " + oldPath);
                        stream.Flush();
                        stream.Close();
                    }
                    //Adattagok módosítása
                    model.AssetTag = resource.AssetTag;
                    model.Description = resource.Description;
                    model.Name = resource.Name;
                    model.TimeLimit = resource.TimeLimit;

                    resourceRepo.UpdateResouce(model);
                    statisticRepo.InsertStatistic(new StatisticModel()
                    {
                        ResourceId = resource.Id,
                        UserId = User.Identity.GetUserId(),
                        StatisticType = StatisticType.ResourceModified,
                        DateTime = DateTime.Now
                    });

                    //Értesítés küldés
                    var users = model.Users.Select(k => k.UserName).ToList();
                    string message = string.Format("{0} módosította {1} erőforrást.", User.Identity.Name, resource.Name);
                    string url = "/Resources/Details/" + resource.Id;
                    NotificationHelper.Send(users, "Erőforrás módosítás", message, resource.ImagePath, url);

                    return RedirectToAction("Index");
                }
                catch (Exception e)
                {
                    log.Error("Módosítás", e);
                    return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
                }
            }
            return View(resource);
        }

        [System.Web.Mvc.Authorize(Roles = "Admin")]
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                log.Warn("BadRequest");
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

            }
            Resource resource = resourceRepo.GetResourceByID((int)id);
            if (resource == null)
            {
                log.Warn("HttpNotFound");
                return HttpNotFound();

            }
            return View(resource);
        }

        [System.Web.Mvc.Authorize(Roles = "Admin")]
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            try
            {
                Resource resource = resourceRepo.GetResourceByID(id);

                //Értesítés küldés
                var users = resource.Users.Select(k => k.UserName).ToList();
                string message = string.Format("{0} törölte {1} erőforrást.", User?.Identity?.Name, resource.Name);
                NotificationHelper.Send(users, "Erőforrás törlés", message, null, null);

                resourceRepo.DeleteResouce(resource.Id); ;
                statisticRepo.InsertStatistic(new StatisticModel()
                {
                    ResourceId = resource.Id,
                    UserId = User.Identity.GetUserId(),
                    StatisticType = StatisticType.ResourceDelete,
                    DateTime = DateTime.Now
                });
                pictureDelete(resource.ImagePath);
            }
            catch (Exception ex)
            {
                log.Error("Delete", ex);
                return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
            }


            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                context.Dispose();
                resourceRepo.Dispose();
                statisticRepo.Dispose();
                userRepo.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
