using DevExpress.Web.Mvc;
using GreenTree.Nachtragsmanagement.Services.Appendix;
using GreenTree.Nachtragsmanagement.Services.Deviation;
using GreenTree.Nachtragsmanagement.Services.User;
using GreenTree.Nachtragsmanagement.Web.Models.Appendix;
using GreenTree.Nachtragsmanagement.Web.Models.Deviation;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;

namespace GreenTree.Nachtragsmanagement.Web.Controllers
{
    public class DataCallbackController : Controller
    {
        private readonly IUserService _userService;
        private readonly IDeviationService _deviationService;
        private readonly IAppendixService _appendixService;

        private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings
        {
            Error = (serializer, ex) => { ex.ErrorContext.Handled = true; }
        };

        public DataCallbackController(
            IUserService userService,
            IDeviationService deviationService,
            IAppendixService appendixService)
        {
            _userService = userService;
            _deviationService = deviationService;
            _appendixService = appendixService;
        }

        #region User

        /// <summary>
        /// Returns a DevExpress ComboBox for all roles 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        public ActionResult RolesComboBox(string settingsKey, string model = null, string type = null)
        {
            return RolesComboBoxExcluded(settingsKey, model, type, null);
        }

        /// <summary>
        /// Returns a DevExpress ComboBox for all roles 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        /// <param name="excludedIdsJson">Ids of the excluded roles.</param>
        public ActionResult RolesComboBoxExcluded(string settingsKey, string model, string type, int[] excludedIds)
        {
            var allRoles = _userService.GetAllRoles();

            if (excludedIds != null)
            {
                foreach (var excludedId in excludedIds)
                {
                    var item = allRoles
                        .FirstOrDefault(s => s.Id == excludedId);

                    allRoles.Remove(item);
                }
            }

            ViewData["AllRoles"] = allRoles;
            ViewData["RolesComboBoxSettings"] = settingsKey;

            if (model != null && type != null)
            {
                var modelType = Type.GetType(type);
                var modelObject = JsonConvert.DeserializeObject(model, modelType, _serializerSettings);

                return PartialView("~/Views/Shared/DataEditorTemplates/_RolesComboBox.cshtml", modelObject);
            }

            return PartialView("~/Views/Shared/DataEditorTemplates/_RolesComboBox.cshtml", null);
        }

        #endregion

        #region Deviations

        /// <summary>
        /// Returns a DevExpress ComboBox for all statuses 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        public ActionResult StatusesComboBox(string settingsKey, string model, string type)
        {
            return StatusesComboBoxExcluded(settingsKey, model, type, null);
        }

        /// <summary>
        /// Returns a DevExpress ComboBox for all statuses 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        /// <param name="excludedIdsJson">Ids of the excluded statuses.</param>
        public ActionResult StatusesComboBoxExcluded(string settingsKey, string model, string type, int[] excludedIds)
        {
            var allStatuses = _deviationService.GetAllStatuses();

            if (excludedIds != null)
            {
                foreach (var excludedId in excludedIds)
                {
                    var item = allStatuses
                        .FirstOrDefault(s => s.Id == excludedId);

                    allStatuses.Remove(item);
                }
            }

            var defaultStatusId =
                allStatuses
                    .Any(s => s.IsDefault)
                        ? allStatuses
                            .First(s => s.IsDefault).Id
                        : -1;

            ViewData["DefaultStatus"] = defaultStatusId;
            ViewData["AllStatuses"] = allStatuses;
            ViewData["StatusesComboBoxSettings"] = settingsKey;

            if (model != null && type != null)
            {
                var modelType = Type.GetType(type);
                var modelObject = JsonConvert.DeserializeObject(model, modelType, _serializerSettings);

                return PartialView("~/Views/Shared/DataEditorTemplates/_StatusesComboBox.cshtml", modelObject);
            }

            return PartialView("~/Views/Shared/DataEditorTemplates/_StatusesComboBox.cshtml", null);
        }

        /// <summary>
        /// Returns a DevExpress ComboBox for all disturbances 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        public ActionResult DisturbancesComboBox(string settingsKey, string model, string type)
        {
            return DisturbancesComboBoxExcluded(settingsKey, model, type, null);
        }

        /// <summary>
        /// Returns a DevExpress ComboBox for all disturbances 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        /// <param name="excludedIdsJson">Ids of the excluded disturbances.</param>
        public ActionResult DisturbancesComboBoxExcluded(string settingsKey, string model, string type, int[] excludedIds)
        {
            var allDisturbances = _deviationService.GetAllDisturbances();

            if (excludedIds != null)
            {
                foreach (var excludedId in excludedIds)
                {
                    var item = allDisturbances
                        .FirstOrDefault(s => s.Id == excludedId);

                    allDisturbances.Remove(item);
                }
            }

            ViewData["AllDisturbances"] = allDisturbances;
            ViewData["DisturbancesComboBoxSettings"] = settingsKey;

            if (model != null && type != null)
            {
                var modelType = Type.GetType(type);
                var modelObject = JsonConvert.DeserializeObject(model, modelType, _serializerSettings);

                return PartialView("~/Views/Shared/DataEditorTemplates/_DisturbancesComboBox.cshtml", modelObject);
            }

            return PartialView("~/Views/Shared/DataEditorTemplates/_DisturbancesComboBox.cshtml", null);
        }

        /// <summary>
        /// Returns a DevExpress ComboBox for all kinds 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        public ActionResult KindsComboBox(string settingsKey, string model, string type)
        {
            return KindsComboBoxExcluded(settingsKey, model, type, null);
        }

        /// <summary>
        /// Returns a DevExpress ComboBox for all kinds 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        /// <param name="excludedIdsJson">Ids of the excluded kinds.</param>
        public ActionResult KindsComboBoxExcluded(string settingsKey, string model, string type, int[] excludedIds)
        {
            var allKinds = _deviationService.GetAllKinds();

            if (excludedIds != null)
            {
                foreach (var excludedId in excludedIds)
                {
                    var item = allKinds
                        .FirstOrDefault(s => s.Id == excludedId);

                    allKinds.Remove(item);
                }
            }

            var defaultKindId =
                allKinds
                    .Any(s => s.IsDefault)
                        ? allKinds
                            .First(s => s.IsDefault).Id
                        : -1;

            ViewData["DefaultKind"] = defaultKindId;
            ViewData["AllKinds"] = allKinds;
            ViewData["KindsComboBoxSettings"] = settingsKey;

            if (model != null && type != null)
            {
                var modelType = Type.GetType(type);
                var modelObject = JsonConvert.DeserializeObject(model, modelType, _serializerSettings);

                return PartialView("~/Views/Shared/DataEditorTemplates/_KindsComboBox.cshtml", modelObject);
            }

            return PartialView("~/Views/Shared/DataEditorTemplates/_KindsComboBox.cshtml", null);
        }

        #endregion

        #region Appendices

        /// <summary>
        /// Returns a DevExpress ComboBox for all states 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        public ActionResult StatesComboBox(string settingsKey, string model, string type)
        {
            return StatesComboBoxExcluded(settingsKey, model, type, null);
        }

        /// <summary>
        /// Returns a DevExpress ComboBox for all states 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        /// <param name="excludedIdsJson">Ids of the excluded states.</param>
        public ActionResult StatesComboBoxExcluded(string settingsKey, string model, string type, int[] excludedIds)
        {
            var allStates = _appendixService.GetAllStates();

            if (excludedIds != null)
            {
                foreach (var excludedId in excludedIds)
                {
                    var item = allStates
                        .FirstOrDefault(s => s.Id == excludedId);

                    allStates.Remove(item);
                }
            }

            var defaultStateId =
                allStates
                    .Any(s => s.IsDefault)
                        ? allStates
                            .First(s => s.IsDefault).Id
                        : -1;

            ViewData["DefaultState"] = defaultStateId;
            ViewData["AllStates"] = allStates;
            ViewData["StatesComboBoxSettings"] = settingsKey;

            if (model != null && type != null)
            {
                var modelType = Type.GetType(type);
                var modelObject = JsonConvert.DeserializeObject(model, modelType, _serializerSettings);

                return PartialView("~/Views/Shared/DataEditorTemplates/_StatesComboBox.cshtml", modelObject);
            }

            return PartialView("~/Views/Shared/DataEditorTemplates/_StatesComboBox.cshtml", null);
        }

        /// <summary>
        /// Returns a DevExpress ComboBox for all categories 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        public ActionResult CategoriesComboBox(string settingsKey, string model, string type)
        {
            return CategoriesComboBoxExcluded(settingsKey, model, type, null);
        }

        /// <summary>
        /// Returns a DevExpress ComboBox for all categories 
        /// </summary>
        /// <param name="settingsKey">Current comboBox settings key.</param>
        /// <param name="model">JSON-serialized model.</param>
        /// <param name="type">Type of model.</param>
        /// <param name="excludedIdsJson">Ids of the excluded categories.</param>
        public ActionResult CategoriesComboBoxExcluded(string settingsKey, string model, string type, int[] excludedIds)
        {
            var allCategories = _appendixService.GetAllCategories();

            if (excludedIds != null)
            {
                foreach (var excludedId in excludedIds)
                {
                    var item = allCategories
                        .FirstOrDefault(s => s.Id == excludedId);

                    allCategories.Remove(item);
                }
            }

            ViewData["AllCategories"] = allCategories;
            ViewData["CategoriesComboBoxSettings"] = settingsKey;

            if (model != null && type != null)
            {
                var modelType = Type.GetType(type);
                var modelObject = JsonConvert.DeserializeObject(model, modelType, _serializerSettings);

                return PartialView("~/Views/Shared/DataEditorTemplates/_CategoriesComboBox.cshtml", modelObject);
            }

            return PartialView("~/Views/Shared/DataEditorTemplates/_CategoriesComboBox.cshtml", null);
        }

        #endregion
    }
}