namespace CARRE_DSS2.Migrations
{
    using CARRE_DSS2.Models;
    using Microsoft.AspNet.Identity;
    using Microsoft.AspNet.Identity.EntityFramework;
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    internal sealed class Configuration : DbMigrationsConfiguration<CARRE_DSS2.Models.ApplicationDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
            AutomaticMigrationDataLossAllowed = true;
        }

        protected override void Seed(ApplicationDbContext context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //

            if (System.Diagnostics.Debugger.IsAttached == false)
                System.Diagnostics.Debugger.Launch();

            //SeedRoles(context);
            //SeedUsers(context);

            ClearRFData(context);

            SeedObservables(context);
            SeedRiskElements(context);
            SeedRiskEvidences(context);
            SeedRiskFactors(context);
        }

        private void ClearRFData(ApplicationDbContext context)
        {

            var rf = context.RiskFactors;

            foreach (var t in rf)
                context.RiskFactors.Remove(t);

            var rEv = context.RiskEvidences;

            foreach (var t in rEv )
                context.RiskEvidences.Remove(t);

            var rEl = context.RiskElements;

            foreach (var t in rEl)
                context.RiskElements.Remove(t);

            var obs = context.Observables;

            foreach (var t in obs)
                context.Observables.Remove(t);

            context.SaveChanges();
        }

        private void SeedRoles(ApplicationDbContext context)
        {
            var roleManager = new RoleManager<Microsoft.AspNet.Identity.EntityFramework.IdentityRole>(new RoleStore<IdentityRole>());

            if (!roleManager.RoleExists("Admin"))
            {
                var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
                role.Name = "Admin";
                roleManager.Create(role);
            }

            if (!roleManager.RoleExists("Doctor"))
            {
                var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
                role.Name = "Doctor";
                roleManager.Create(role);
            }
        }

        private void SeedUsers(ApplicationDbContext context)
        {
            var store = new UserStore<ApplicationUser>(context);
            var manager = new UserManager<ApplicationUser>(store);

            if (!context.Users.Any(u => u.UserName == "Admin"))
            {
                var user = new ApplicationUser { UserName = "Admin" };
                var adminresult = manager.Create(user, "123456");

                if (adminresult.Succeeded)
                    manager.AddToRole(user.Id, "Admin");
            }

            if (!context.Users.Any(u => u.UserName == "MedExp"))
            {
                var user = new ApplicationUser { UserName = "MedExp" };
                var res = manager.Create(user, "123456");

                if (res.Succeeded)
                    manager.AddToRole(user.Id, "Doctor");
            }
        }

        private void SeedObservables(ApplicationDbContext context)
        {

            var rep = new CarreRiskRepository();
            var obs = rep.getObservables();

            int i = 1;
            foreach (Observable o in obs)
            {
                o.Id = i;

                //if (o.Type == "http://carre.kmi.open.ac.uk/ontology/risk.owl#clinical_observable")
                //    o.Type = "Clinical observable";
                //else if (o.Type == "http://carre.kmi.open.ac.uk/ontology/risk.owl#personal_observable")
                //    o.Type = "Personal observable";


                i++;
                context.Set<Observable>().AddOrUpdate(o);
            }

            context.SaveChanges();
        }

        private void SeedRiskElements(ApplicationDbContext context)
        {
            var rep = new CarreRiskRepository();

            var re = rep.getRiskElements();

            int i = 1;
            foreach (RiskElement r in re)
            {
                r.Id = i;

                if (r.Type == "http://carre.kmi.open.ac.uk/ontology/risk.owl#biomedical_risk_element ")
                    r.Type = "Biomedical";
                else if (r.Type == "http://carre.kmi.open.ac.uk/ontology/risk.owl#genetic_risk_element ")
                    r.Type = "Genetic";
                else if (r.Type == "http://carre.kmi.open.ac.uk/ontology/risk.owl#demographic_risk_element ")
                    r.Type = "Demographic";
                else if (r.Type == "http://carre.kmi.open.ac.uk/ontology/risk.owl#behavioural_risk_element ")
                    r.Type = "Behavioural";

                i++;

                var obList = rep.getObservablesOfRiskElement(r.Node);

                foreach (String obNode in obList)
                {
                    var obsv = context.Observables.Single(o => o.Node == obNode);
                    r.Observables.Add(obsv);
                }

                context.Set<RiskElement>().AddOrUpdate(r);
            }

            context.SaveChanges();
        }

        private void SeedRiskEvidences(ApplicationDbContext context)
        {
            var rep = new CarreRiskRepository();

            var re = rep.getRiskEvidences();

            int i = 1;
            foreach (RiskEvidence r in re)
            {
                r.Id = i;

                if (r.RatioType == "http://carre.kmi.open.ac.uk/ontology/risk.owl#Relative_Risk ")
                    r.RatioType = "Relative";
                else if (r.RatioType == "http://carre.kmi.open.ac.uk/ontology/risk.owl#Hazard_Ratio ")
                    r.RatioType = "Hazard";
                else if (r.RatioType == "http://carre.kmi.open.ac.uk/ontology/risk.owl#Odds_Ratio ")
                    r.RatioType = "Odds";

                i++;

                var obList = rep.getObservablesOfRiskEvidence(r.Node);

                foreach (String obNode in obList)
                {
                    try
                    {
                        r.Observables.Add(context.Observables.Single(o => o.Node == obNode));
                    }
                    catch
                    {
                        throw new Exception(obNode);
                    }
                }

                context.Set<RiskEvidence>().AddOrUpdate(r);
            }

            context.SaveChanges();
        }

        private void SeedRiskFactors(ApplicationDbContext context)
        {
            var rep = new CarreRiskRepository();

            var rf = rep.getRiskFactors();

            int i = 1;
            foreach (RiskFactor r in rf)
            {
                r.Id = i;

                if (r.AssociationType == "http://carre.kmi.open.ac.uk/ontology/risk.owl#risk_factor_association_type_causes")
                    r.AssociationType = "Causes";
                else if (r.AssociationType == "http://carre.kmi.open.ac.uk/ontology/risk.owl#risk_factor_association_type_issue_in")
                    r.AssociationType = "Issue in";

                i++;

                var reList = rep.getRiskEvidencesOfRiskFactor(r.Node);

                //adding risk evidences
                foreach (String reNode in reList)
                {
                    var temp = context.RiskEvidences.Single(re => re.Node == reNode);
                    r.RiskEvidences.Add(temp);
                }

                //adding target risk element
                var targetStr = rep.getTargetRiskElementOfRiskFactor(r.Node);
                r.Target = context.RiskElements.Single(re => re.Node == targetStr);

                //adding source risk elements
                var sourceList = rep.getSourceRiskElementsOfRiskFactor(r.Node);
                foreach (String reNode in sourceList)
                {
                    var temp = context.RiskElements.Single(re => re.Node == reNode);
                    r.Sources.Add(temp);
                }


                context.Set<RiskFactor>().AddOrUpdate(r);

            }

            context.SaveChanges();
        }
    }
}