using System.Linq;
using GTANetworkAPI;
using Newtonsoft.Json.Linq;
using ReallifeGamemode.Server.Extensions;
using ReallifeGamemode.Server.Models;

namespace ReallifeGamemode.Server.Managers
{
    public class CharacterCreator : Script
    {
        public CharacterCreator()
        {
        }

        [RemoteEvent("creatorSave")]
        public void CreatorSave(Client player, bool gender, string parentData, string featureData, string appearanceData, string hairAndColorData)
        {
            var jParentData = JObject.Parse(parentData);
            var jFeatureData = JArray.Parse(featureData);
            var jAppearanceData = JArray.Parse(appearanceData);
            var jHairAndColorData = JArray.Parse(hairAndColorData);

            byte father = jParentData.Value<byte>("Father");
            byte mother = jParentData.Value<byte>("Mother");
            float similarity = jParentData.Value<float>("Similarity");
            float skinSimilarity = jParentData.Value<float>("SkinSimilarity");

            float noseWidth = jFeatureData.Value<float>(0);
            float noseBottomHeight = jFeatureData.Value<float>(1);
            float noseTipLength = jFeatureData.Value<float>(2);
            float noseBridgeDepth = jFeatureData.Value<float>(3);
            float noseTipHeight = jFeatureData.Value<float>(4);
            float noseBroken = jFeatureData.Value<float>(5);
            float browHeight = jFeatureData.Value<float>(6);
            float browDepth = jFeatureData.Value<float>(7);
            float cheekboneHeight = jFeatureData.Value<float>(8);
            float cheekboneWidth = jFeatureData.Value<float>(9);
            float cheekDepth = jFeatureData.Value<float>(10);
            float eyeSize = jFeatureData.Value<float>(11);
            float lipThickness = jFeatureData.Value<float>(12);
            float jawWidth = jFeatureData.Value<float>(13);
            float jawShape = jFeatureData.Value<float>(14);
            float chinHeight = jFeatureData.Value<float>(15);
            float chinDepth = jFeatureData.Value<float>(16);
            float chinWidth = jFeatureData.Value<float>(17);
            float chinIndent = jFeatureData.Value<float>(18);
            float neckWidth = jFeatureData.Value<float>(19);

            byte blemishes = jAppearanceData[0].Value<byte>("Value");
            float blemishesOpacity = jAppearanceData[0].Value<byte>("Opacity");
            byte facialHair = jAppearanceData[1].Value<byte>("Value");
            float facialHairOpacity = jAppearanceData[1].Value<byte>("Opacity");
            byte eyebrows = jAppearanceData[2].Value<byte>("Value");
            float eyebrowsOpacity = jAppearanceData[2].Value<byte>("Opacity");
            byte ageing = jAppearanceData[3].Value<byte>("Value");
            float ageingOpacity = jAppearanceData[3].Value<byte>("Opacity");
            byte makeup = jAppearanceData[4].Value<byte>("Value");
            float makeupOpacity = jAppearanceData[4].Value<byte>("Opacity");
            byte blush = jAppearanceData[5].Value<byte>("Value");
            float blushOpacity = jAppearanceData[5].Value<byte>("Opacity");
            byte complexion = jAppearanceData[6].Value<byte>("Value");
            float complexionOpacity = jAppearanceData[6].Value<byte>("Opacity");
            byte sunDamage = jAppearanceData[7].Value<byte>("Value");
            float sunDamageOpacity = jAppearanceData[7].Value<byte>("Opacity");
            byte lipstick = jAppearanceData[8].Value<byte>("Value");
            float lipstickOpacity = jAppearanceData[8].Value<byte>("Opacity");
            byte freckles = jAppearanceData[9].Value<byte>("Value");
            float frecklesOpacity = jAppearanceData[9].Value<byte>("Opacity");
            byte chestHair = jAppearanceData[10].Value<byte>("Value");
            float chestHairOpacity = jAppearanceData[10].Value<byte>("Opacity");

            byte hair = jHairAndColorData.Value<byte>(0);
            byte hairColor = jHairAndColorData.Value<byte>(1);
            byte hairHighlightColor = jHairAndColorData.Value<byte>(2);
            byte eyebrowColor = jHairAndColorData.Value<byte>(3);
            byte beardColor = jHairAndColorData.Value<byte>(4);
            byte eyeColor = jHairAndColorData.Value<byte>(5);
            byte blushColor = jHairAndColorData.Value<byte>(6);
            byte lipstickColor = jHairAndColorData.Value<byte>(7);
            byte chestHairColor = jHairAndColorData.Value<byte>(8);

            using (var saveCharacter = new DatabaseContext())
            {
                var character = new Entities.Character
                {
                    UserId = player.GetUser().Id,
                    Gender = gender,
                    Father = father,
                    Mother = mother,
                    Similarity = similarity,
                    SkinSimilarity = skinSimilarity,

                    NoseWidth = noseWidth,
                    NoseBottomHeight = noseBottomHeight,
                    NoseTipLength = noseTipLength,
                    NoseBridgeDepth = noseBridgeDepth,
                    NoseTipHeight = noseTipHeight,
                    NoseBroken = noseBroken,
                    BrowHeight = browHeight,
                    BrowDepth = browDepth,
                    CheekboneHeight = cheekboneHeight,
                    CheekboneWidth = cheekboneWidth,
                    CheekDepth = cheekDepth,
                    EyeSize = eyeSize,
                    LipThickness = lipThickness,
                    JawWidth = jawWidth,
                    JawShape = jawShape,
                    ChinHeight = chinHeight,
                    ChinDepth = chinDepth,
                    ChinWidth = chinWidth,
                    ChinIndent = chinIndent,
                    NeckWidth = neckWidth,

                    Blemishes = blemishes,
                    BlemishesOpacity = blemishesOpacity,
                    FacialHair = facialHair,
                    FacialHairOpacity = facialHairOpacity,
                    Eyebrows = eyebrows,
                    EyebrowsOpacity = eyebrowsOpacity,
                    Ageing = ageing,
                    AgeingOpacity = ageingOpacity,
                    Makeup = makeup,
                    MakeupOpacity = makeupOpacity,
                    Blush = blush,
                    BlushOpacity = blushOpacity,
                    Complexion = complexion,
                    ComplexionOpacity = complexionOpacity,
                    SunDamage = sunDamage,
                    SunDamageOpacity = sunDamageOpacity,
                    Lipstick = lipstick,
                    LipstickOpacity = lipstickOpacity,
                    Freckles = freckles,
                    FrecklesOpacity = frecklesOpacity,
                    ChestHair = chestHair,
                    ChestHairOpacity = chestHairOpacity,

                    Hair = hair,
                    HairColor = hairColor,
                    HairHighlightColor = hairHighlightColor,
                    EyebrowColor = eyebrowColor,
                    BeardColor = beardColor,
                    EyeColor = eyeColor,
                    BlushColor = blushColor,
                    LipstickColor = lipstickColor,
                    ChestHairColor = chestHairColor
                };

                saveCharacter.Characters.Add(character);
                saveCharacter.SaveChanges();

                var userId = player.GetUser().Id;
                var user = saveCharacter.Users.SingleOrDefault(u => u.Id == userId);

                user.CharacterId = character.Id;
                saveCharacter.SaveChanges();
            }
            //HeadOverlay makeupHo = new HeadOverlay()
            //{
            //    Index = 0,
            //    Opacity = 0.0f,
            //    Color = 0,
            //    SecondaryColor = 0
            //};
            //HeadOverlay blushHo = new HeadOverlay()
            //{
            //    Index = 0,
            //    Opacity = 0.0f,
            //    Color = 0,
            //    SecondaryColor = 0
            //};
            //player.SetHeadOverlay(4, makeupHo);
            //player.SetHeadOverlay(5, blushHo);
            NAPI.Player.SpawnPlayer(player, Main.DEFAULT_SPAWN_POSITION, Main.DEFAULT_SPAWN_HEADING);
            player.TriggerEvent("draw", player.Name, player.Handle.Value);
            player.Dimension = 0;
        }

        /// <summary>
        /// Wendet den Character eines Spielers auf diesen an
        /// </summary>
        /// <param name="player">Der Client, dessen Aussehen man setzen will</param>
        public static void ApplyCharacter(Client player)
        {
            var userId = player.GetUser().Id;
            using (var loadCharacter = new DatabaseContext())
            {
                var character = loadCharacter.Characters.SingleOrDefault(c => c.UserId == userId);

                if (character == null) return;

                //Männlich / Weiblich
                if (character.Gender == false)
                {
                    player.SetSkin(PedHash.FreemodeMale01);
                }
                else
                {
                    player.SetSkin(PedHash.FreemodeFemale01);
                }

                //Gesichtszüge
                float[] faceFeatures = new float[] { character.NoseWidth, character.NoseBottomHeight, character.NoseTipLength, character.NoseBridgeDepth, character.NoseTipHeight,
                    character.NoseBroken, character.BrowHeight, character.BrowDepth, character.CheekboneHeight, character.CheekboneWidth,
                    character.CheekboneWidth, character.CheekDepth, character.EyeSize, character.LipThickness, character.JawWidth,
                    character.JawShape, character.ChinHeight, character.ChinDepth, character.ChinWidth, character.ChinIndent, character.NeckWidth };

                for (var i = 0; i < faceFeatures.Length; i++)
                {
                    player.SetFaceFeature(i, faceFeatures[i]);
                }

                //Gesichtsmerkmale
                HeadOverlay blemishes = new HeadOverlay()
                {
                    Index = character.Blemishes,
                    Opacity = character.BlemishesOpacity,
                    Color = 255,
                    SecondaryColor = 255
                };
                HeadOverlay facialHair = new HeadOverlay()
                {
                    Index = character.FacialHair,
                    Opacity = character.FacialHairOpacity,
                    Color = character.BeardColor,
                    SecondaryColor = 255
                };
                HeadOverlay eyebrows = new HeadOverlay()
                {
                    Index = character.Eyebrows,
                    Opacity = character.EyebrowsOpacity,
                    Color = character.EyebrowColor,
                    SecondaryColor = 255
                };
                HeadOverlay ageing = new HeadOverlay()
                {
                    Index = character.Ageing,
                    Opacity = character.AgeingOpacity,
                    Color = 255,
                    SecondaryColor = 255
                };
                HeadOverlay makeup = new HeadOverlay()
                {
                    Index = character.Makeup,
                    Opacity = character.MakeupOpacity,
                    Color = 255,
                    SecondaryColor = 255
                };
                HeadOverlay blush = new HeadOverlay()
                {
                    Index = character.Blush,
                    Opacity = character.BlushOpacity,
                    Color = character.BlushColor,
                    SecondaryColor = 255
                };
                HeadOverlay complexion = new HeadOverlay()
                {
                    Index = character.Complexion,
                    Opacity = character.ComplexionOpacity,
                    Color = 255,
                    SecondaryColor = 255
                };
                HeadOverlay sunDamage = new HeadOverlay()
                {
                    Index = character.SunDamage,
                    Opacity = character.SunDamageOpacity,
                    Color = 255,
                    SecondaryColor = 255
                };
                HeadOverlay lipstick = new HeadOverlay()
                {
                    Index = character.Lipstick,
                    Opacity = character.LipstickOpacity,
                    Color = character.LipstickColor,
                    SecondaryColor = 255
                };
                HeadOverlay freckles = new HeadOverlay()
                {
                    Index = character.Freckles,
                    Opacity = character.FrecklesOpacity,
                    Color = 255,
                    SecondaryColor = 255
                };
                HeadOverlay chestHair = new HeadOverlay()
                {
                    Index = character.ChestHair,
                    Opacity = character.ChestHairOpacity,
                    Color = character.ChestHairColor,
                    SecondaryColor = 255
                };

                player.SetHeadOverlay(0, blemishes);
                player.SetHeadOverlay(1, facialHair);
                player.SetHeadOverlay(2, eyebrows);
                player.SetHeadOverlay(3, ageing);
                player.SetHeadOverlay(4, makeup);
                player.SetHeadOverlay(5, blush);
                player.SetHeadOverlay(6, complexion);
                player.SetHeadOverlay(7, sunDamage);
                player.SetHeadOverlay(8, lipstick);
                player.SetHeadOverlay(9, freckles);
                player.SetHeadOverlay(10, chestHair);
                player.SetHeadOverlay(11, blemishes);
                player.SetHeadOverlay(12, blemishes);


                //Gesicht (Vererbung durch Mutter / Vater)
                HeadBlend headBlend = new HeadBlend()
                {
                    ShapeFirst = character.Mother,
                    ShapeSecond = character.Father,
                    ShapeThird = 0,
                    SkinFirst = character.Mother,
                    SkinSecond = character.Father,
                    SkinThird = 0,
                    ShapeMix = character.Similarity,
                    SkinMix = character.SkinSimilarity,
                    ThirdMix = 0.0f
                };
                NAPI.Player.SetPlayerHeadBlend(player, headBlend);

                //Haare und Haarfarbe
                player.SetClothes(2, character.Hair, 0);
                NAPI.Player.SetPlayerHairColor(player, character.HairColor, character.HairHighlightColor);

                //Augenfarbe
                NAPI.Player.SetPlayerEyeColor(player, character.EyeColor);

            }
        }
    }
}
