using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.JsonPatch;
using EnumsNET;
using AyaNova.Util;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
using AyaNova.Models;


namespace AyaNova.Biz
{


    internal class UserOptionsBiz : BizObject
    {

        internal UserOptionsBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
        {
            ct = dbcontext;
            UserId = currentUserId;
            CurrentUserRoles = userRoles;
            BizType = AyaType.UserOptions;
        }


        ////////////////////////////////////////////////////////////////////////////////////////////////
        /// GET

        //Get one
        internal async Task<UserOptions> GetAsync(long fetchId)
        {
            //NOTE: get by UserId as there is a 1:1 relationship, not by useroptions id
            //This is simple so nothing more here, but often will be copying to a different output object or some other ops
            return await ct.UserOptions.SingleOrDefaultAsync(m => m.UserId == fetchId);
        }


        ////////////////////////////////////////////////////////////////////////////////////////////////
        //UPDATE
        //

        //put
        internal bool Put(UserOptions dbObj, UserOptions inObj)
        {
            //preserve the owner ID if none was specified
            if (inObj.OwnerId == 0)
                inObj.OwnerId = dbObj.OwnerId;
                
            //Replace the db object with the PUT object
            CopyObject.Copy(inObj, dbObj, "Id, UserId, OwnerId");
            //Set "original" value of concurrency token to input token
            //this will allow EF to check it out
            ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = inObj.ConcurrencyToken;

            Validate(dbObj);
            if (HasErrors)
                return false;

            ct.SaveChanges();
            //Log
            EventLogProcessor.LogEventToDatabase(new Event(UserId, dbObj.Id, AyaType.UserOptions, AyaEvent.Modified), ct);
            return true;
        }

        //patch
        internal bool Patch(UserOptions dbObj, JsonPatchDocument<UserOptions> objectPatch, uint concurrencyToken)
        {
            //Validate Patch is allowed
            if (!ValidateJsonPatch<UserOptions>.Validate(this, objectPatch, "UserId")) return false;

            //Do the patching
            objectPatch.ApplyTo(dbObj);

            ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = concurrencyToken;
            Validate(dbObj);
            if (HasErrors)
                return false;

            ct.SaveChanges();
            //Log
            EventLogProcessor.LogEventToDatabase(new Event(UserId, dbObj.Id, AyaType.UserOptions, AyaEvent.Modified), ct);
            return true;
        }




        ////////////////////////////////////////////////////////////////////////////////////////////////
        //VALIDATION
        //

        //Can save or update?
        private void Validate(UserOptions inObj)
        {
            //UserOptions is never new, it's created with the User object so were only here for an edit


            //OwnerId required
            if (inObj.OwnerId == 0)
                AddError(ValidationErrorType.RequiredPropertyEmpty, "OwnerId");

            //OwnerId required
            if (inObj.UserId == 0)
                AddError(ValidationErrorType.RequiredPropertyEmpty, "UserId");

            //LOOKAT:Validate email address is legitimate (I put the EMailAddress attribute on the field in the model so I think it might validate)

            return;
        }



        /////////////////////////////////////////////////////////////////////

    }//eoc


}//eons

