using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using SessionCompanion.Database.Tables;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SessionCompanion.Database
{
    public class ApplicationDbContext : DbContext
    {
        public virtual DbSet<Alignment> Alignments { get; set; }
        public virtual DbSet<Background> Backgrounds { get; set; }
        public virtual DbSet<Biography> Biographies { get; set; }
        public virtual DbSet<Character> Characters { get; set; }
        public virtual DbSet<Charisma> Charismas { get; set; }
        public virtual DbSet<Class> Classes { get; set; }
        public virtual DbSet<Constitution> Constitutions { get; set; }
        public virtual DbSet<Dexterity> Dexterities { get; set; }
        public virtual DbSet<Intelligence> Intelligences { get; set; }
        public virtual DbSet<Race> Races { get; set; }
        public virtual DbSet<Statistics> Statistics { get; set; }
        public virtual DbSet<Strength> Strengths { get; set; }
        public virtual DbSet<User> Users { get; set; }
        public virtual DbSet<Wisdom> Wisdoms { get; set; }
        public virtual DbSet<Spell> Spells { get; set; }
        public virtual DbSet<CharacterSpell> CharacterSpells { get; set; }
        public virtual DbSet<CharacterSpellSlots> CharacterSpellSlots { get; set; }
        public virtual DbSet<Armor> Armors { get; set; }
        public virtual DbSet<CharacterArmor> CharacterArmors { get; set; }
        public virtual DbSet<Weapon> Weapons { get; set; }
        public virtual DbSet<CharacterWeapon> CharacterWeapons { get; set; }
        public virtual DbSet<OtherEquipment> OtherEquipment { get; set; }
        public virtual DbSet<CharacterOtherEquipment> CharacterOtherEquipment { get; set; }
        public virtual DbSet<Monster> Monsters { get; set; }
        public virtual DbSet<MonsterAction> MonsterActions { get; set; }
        public virtual DbSet<MonsterLegendaryAction> MonsterLegendaryActions { get; set; }
        public virtual DbSet<MonsterSpecialAbility> MonsterSpecialAbilities { get; set; }
        public virtual DbSet<GameAction> GameActions { get; set; }
        public virtual DbSet<LegendaryAction> LegendaryActions { get; set; }
        public virtual DbSet<SpecialAbility> SpecialAbilities { get; set; }
        public virtual DbSet<Shopkeeper> Shopkeepers { get; set; }
        public virtual DbSet<ShopkeeperItem> ShopkeeperItems { get; set; }

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }

        public List<SpecialAbility> SpecialAbilitiesList { get; set; }
        public List<LegendaryAction> LegendaryActionsList { get; set; }
        public List<GameAction> GameActionsList { get; set; }

        protected IEnumerable<Weapon> SeedWeapon()
        {
            const string file = "../SessionCompanion.Database/JsonData/weapons.json";
            List<Weapon> weapons = new List<Weapon>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jweapons = JArray.Parse(json);
                foreach (dynamic item in jweapons)
                    weapons.Add(SeedFromJsons.SingleWeaponSeeder(item));
            }
            return weapons;
        }
        protected IEnumerable<Armor> SeedArmor()
        {
            const string file = "../SessionCompanion.Database/JsonData/armors.json";
            List<Armor> armors = new List<Armor>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jactions = JArray.Parse(json);
                int id = 1;
                foreach (dynamic item in jactions)
                {
                    armors.Add(SeedFromJsons.SingleArmorSeeder(item, id));
                    id++;
                }
            }
            return armors;
        }
        protected IEnumerable<OtherEquipment> SeedOtherEquipment()
        {
            const string file = "../SessionCompanion.Database/JsonData/otherEquipments.json";
            List<OtherEquipment> otherEquipment = new List<OtherEquipment>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jactions = JArray.Parse(json);
                int id = 1;
                foreach (dynamic item in jactions)
                {
                    otherEquipment.Add(SeedFromJsons.SingleOtherEquipmentSeeder(item, id));
                    id++;
                }
            }
            return otherEquipment;
        }
        protected IEnumerable<Spell> SeedSpell()
        {
            const string file = "../SessionCompanion.Database/JsonData/spells.json";
            List<Spell> spells = new List<Spell>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jspells = JArray.Parse(json);
                foreach (dynamic item in jspells)
                    spells.Add(SeedFromJsons.SingleSpellSeeder(item));
            }
            return spells;
        }
        protected IEnumerable<SpecialAbility> SeedSpecialAbilities()
        {
            const string file = "../SessionCompanion.Database/JsonData/monsters.json";
            List<SpecialAbility> specAbilities = new List<SpecialAbility>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jabilites = JArray.Parse(json);
                int id = 1;
                foreach (dynamic item in jabilites)
                {
                    if (item.special_abilities != null)
                    {
                        foreach (dynamic sp in item.special_abilities)
                        {
                            if (specAbilities.Find(x => x.Name == (string)sp.name) is null)
                            {
                                specAbilities.Add(SeedFromJsons.SingleSpecialAbilitySeeder(sp, id));
                                id++;
                            }
                        }
                    }
                }
            }
            SpecialAbilitiesList = specAbilities;
            return specAbilities;
        }
        protected IEnumerable<GameAction> SeedActions()
        {
            const string file = "../SessionCompanion.Database/JsonData/monsters.json";
            List<GameAction> gameActions = new List<GameAction>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jactions = JArray.Parse(json);
                int id = 1;
                foreach (dynamic item in jactions)
                {
                    if (item.actions != null)
                    {
                        foreach (dynamic a in item.actions)
                        {
                            if (gameActions.Find(x => x.Name == (string)a.name) is null)
                            {
                                gameActions.Add(SeedFromJsons.SingleActionSeeder(a, id));
                                id++;
                            }
                        }
                    }
                }
            }
            GameActionsList = gameActions;
            return gameActions;
        }
        protected IEnumerable<LegendaryAction> SeedLegendaryActions()
        {
            const string file = "../SessionCompanion.Database/JsonData/monsters.json";
            List<LegendaryAction> legendaryActions = new List<LegendaryAction>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jlegendaryactions = JArray.Parse(json);
                int id = 1;
                foreach (dynamic item in jlegendaryactions)
                {
                    if (item.legendary_actions != null)
                    {
                        foreach (dynamic la in item.legendary_actions)
                        {
                            if (legendaryActions.Find(x => x.Name == (string)la.name) is null)
                            {
                                legendaryActions.Add(SeedFromJsons.SingleLegendaryActionSeeder(la, id));
                                id++;
                            }
                        }
                    }
                }
            }
            LegendaryActionsList = legendaryActions;
            return legendaryActions;
        }
        protected IEnumerable<Monster> SeedMonster()
        {
            const string file = "../SessionCompanion.Database/JsonData/monsters.json";
            List<Monster> monsters = new List<Monster>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jmonsters = JArray.Parse(json);
                foreach (dynamic item in jmonsters)
                    monsters.Add(SeedFromJsons.SingleMonsterSeeder(item));
            }
            return monsters;
        }
        protected IEnumerable<MonsterSpecialAbility> SeedMonsterSpecialAbilities()
        {
            const string file = "../SessionCompanion.Database/JsonData/monsters.json";
            List<MonsterSpecialAbility> monsterSpecialAbilities = new List<MonsterSpecialAbility>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jabilities = JArray.Parse(json);
                int id = 1;
                foreach (dynamic item in jabilities)
                {
                    if (item.special_abilities != null)
                    {
                        foreach (dynamic a in item.special_abilities)
                        {
                            var abilityId = SpecialAbilitiesList.Find(x => x.Name == (string)a.name).Id;
                            monsterSpecialAbilities.Add(new MonsterSpecialAbility { Id = id, MonsterId = (int)item.index, SpecialAbilityId = abilityId });
                            id++;
                        }
                    }
                }
            }
            return monsterSpecialAbilities;
        }
        protected IEnumerable<MonsterAction> SeedMonsterActions()
        {
            const string file = "../SessionCompanion.Database/JsonData/monsters.json";
            List<MonsterAction> monsterActions = new List<MonsterAction>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jactions = JArray.Parse(json);
                int id = 1;
                foreach (dynamic item in jactions)
                {
                    if (item.actions != null)
                    {
                        foreach (dynamic a in item.actions)
                        {
                            var abilityId = GameActionsList.Find(x => x.Name == (string)a.name).Id;
                            monsterActions.Add(new MonsterAction { Id = id, MonsterId = (int)item.index, GameActionId = abilityId });
                            id++;
                        }
                    }
                }
            }
            return monsterActions;
        }
        protected IEnumerable<MonsterLegendaryAction> SeedMonsterLegendaryActions()
        {
            const string file = "../SessionCompanion.Database/JsonData/monsters.json";
            List<MonsterLegendaryAction> monsterLegendaryActions = new List<MonsterLegendaryAction>();
            using (StreamReader reader = new StreamReader(file))
            {
                var json = reader.ReadToEnd();
                dynamic jactions = JArray.Parse(json);
                int id = 1;
                foreach (dynamic item in jactions)
                {
                    if (item.legendary_actions != null)
                    {
                        foreach (dynamic a in item.legendary_actions)
                        {
                            var actionId = LegendaryActionsList.Find(x => x.Name == (string)a.name).Id;
                            monsterLegendaryActions.Add(new MonsterLegendaryAction { Id = id, MonsterId = (int)item.index, LegendaryActionId = actionId });
                            id++;
                        }
                    }
                }
            }
            return monsterLegendaryActions;
        }
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            builder.Entity<User>().HasData(SeedData.SeedUsers());
            builder.Entity<Character>().HasData(SeedData.SeedCharacter());
            builder.Entity<Race>().HasData(SeedData.SeedRace());
            builder.Entity<Class>().HasData(SeedData.SeedClass());
            builder.Entity<Alignment>().HasData(SeedData.SeedAlignment());
            builder.Entity<Background>().HasData(SeedData.SeedBackground());
            builder.Entity<Biography>().HasData(SeedData.SeedBiography());
            builder.Entity<Statistics>().HasData(SeedData.SeedStatistics());
            builder.Entity<Weapon>().HasData(SeedWeapon());
            builder.Entity<Armor>().HasData(SeedArmor());
            builder.Entity<OtherEquipment>().HasData(SeedOtherEquipment());
            builder.Entity<CharacterWeapon>().HasData(SeedData.SeedCharacterWeapon());
            builder.Entity<CharacterArmor>().HasData(SeedData.SeedCharacterArmor());
            builder.Entity<CharacterOtherEquipment>().HasData(SeedData.SeedCharacterOtherEquipment());
            builder.Entity<Charisma>().HasData(SeedData.SeedCharisma());
            builder.Entity<Constitution>().HasData(SeedData.SeedConstitution());
            builder.Entity<Dexterity>().HasData(SeedData.SeedDexterity());
            builder.Entity<Intelligence>().HasData(SeedData.SeedIntelligence());
            builder.Entity<Strength>().HasData(SeedData.SeedStrength());
            builder.Entity<Wisdom>().HasData(SeedData.SeedWisdom());
            builder.Entity<Spell>().HasData(SeedSpell());
            builder.Entity<CharacterSpell>().HasData(SeedData.SeedCharacterSpell());
            builder.Entity<CharacterSpellSlots>().HasData(SeedData.SeedCharacterSpellSlot());
            builder.Entity<Monster>().HasData(SeedMonster());
            builder.Entity<SpecialAbility>().HasData(SeedSpecialAbilities());
            builder.Entity<LegendaryAction>().HasData(SeedLegendaryActions());
            builder.Entity<GameAction>().HasData(SeedActions());
            builder.Entity<MonsterSpecialAbility>().HasData(SeedMonsterSpecialAbilities());
            builder.Entity<MonsterAction>().HasData(SeedMonsterActions());
            builder.Entity<MonsterLegendaryAction>().HasData(SeedMonsterLegendaryActions());
            builder.Entity<Shopkeeper>().HasData(SeedData.SeedSchopkeepers());
            builder.Entity<ShopkeeperItem>().HasData(SeedData.SeedShopkeeperItems());
        }
    }
}