using Coscine.Database.DataModel;
using Coscine.Database.Util;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Coscine.Database.Models
{
    public class ActivatedFeaturesModel : DatabaseModel<ActivatedFeature>
    {
        public override Expression<Func<ActivatedFeature, Guid>> GetIdFromObject()
        {
            return databaseObject => databaseObject.Id;
        }

        public override DbSet<ActivatedFeature> GetITableFromDatabase(CoscineDB db)
        {
            return db.ActivatedFeatures;
        }

        public override void SetObjectId(ActivatedFeature databaseObject, Guid id)
        {
            databaseObject.Id = id;
        }

        public bool IsFeatureActive(Guid projectId, string sharepointId)
        {
            return GetAllWhere((activatedFeatures) => activatedFeatures.ProjectId == projectId
                        && activatedFeatures.Feature.SharepointId == sharepointId).Count() >= 1;
        }

        public bool IsFeatureActive(Guid projectId, Guid featureId)
        {
            return GetAllWhere((activatedFeatures) => activatedFeatures.ProjectId == projectId
                        && activatedFeatures.FeatureId == featureId).Count() >= 1;
        }

        public void ActivateFeature(Guid projectId, Guid featureId)
        {
            if (!IsFeatureActive(projectId, featureId))
            {
                Insert(new ActivatedFeature
                    {
                        ProjectId = projectId,
                        FeatureId = featureId
                    });
            }
        }

        public void DeactivateFeature(Guid projectId, Guid featureId)
        {
            if (IsFeatureActive(projectId, featureId))
            {
                foreach(var feature in GetAllWhere((activatedFeatures) => activatedFeatures.FeatureId == featureId
                        && activatedFeatures.ProjectId == projectId)) {
                    Delete(feature);
                }
                
            }
        }

        public void ActivateAllFeatures(Project project)
        {
            ActivateAllFeatures(project.Id);
        }

        public void ActivateAllFeatures(Guid projectId)
        {
            foreach (var feature in GetInactiveFeatures(projectId))
            {
                ActivateFeature(projectId, feature.Id);
            }
        }
        public void DeactivateAllFeatures(Project project)
        {
            DeactivateAllFeatures(project.Id);
        }

        public void DeactivateAllFeatures(Guid projectId)
        {
            foreach (var feature in GetActiveFeatures(projectId))
            {
                DeactivateFeature(projectId, feature.Id);
            }
        }

        public IEnumerable<Feature> GetInactiveFeatures(Project project)
        {
            return GetInactiveFeatures(project.Id);
        }

        public IEnumerable<Feature> GetInactiveFeatures(Guid projectId)
        {
            return DatabaseConnection.ConnectToDatabase((db) =>
            {
                return (
                    from features in db.Features
                    where !(
                        from activatedFeatures in db.ActivatedFeatures
                        join feature in db.Features on activatedFeatures.FeatureId equals feature.Id
                        join project in db.Projects on activatedFeatures.ProjectId equals project.Id
                        where project.Id == projectId
                        select feature
                    ).Contains(features)
                    select features).Distinct().ToList();
            });
        }

        public IEnumerable<Feature> GetActiveFeatures(Project project)
        {
            return GetActiveFeatures(project.Id);
        }

        public IEnumerable<Feature> GetActiveFeatures(Guid projectId)
        {
            return DatabaseConnection.ConnectToDatabase((db) =>
            {
                return (
                    from activatedFeatures in db.ActivatedFeatures
                    join feature in db.Features on activatedFeatures.FeatureId equals feature.Id
                    join project in db.Projects on activatedFeatures.ProjectId equals project.Id
                    where project.Id == projectId
                    select feature).Distinct().ToList();
            });
        }
    }
}