using Microsoft.Xna.Framework;

using Celeste.Mod.CelesteNet;
using Celeste.Mod.CelesteNet.Client;
using Celeste.Mod.CelesteNet.Client.Entities;
using Celeste.Mod.CelesteNet.DataTypes;
using System.Collections.Generic;

namespace Celeste.Mod.Eevee_Skinmod {
    //Taken from the Avali skin, dont really know how it works
    public class CelesteNetEeveeComponent : CelesteNetGameComponent {
        private static EeveeSettings ModuleSettings => EeveeModule.Settings;
        public static CelesteNetEeveeComponent Instance;

        private CelesteNetClientContext Ctx;

        public CelesteNetEeveeComponent(CelesteNetClientContext context, Game game) : base(context, game) {
            Instance = this;
            Ctx = context;
        }

        public void Handle(CelesteNetConnection con, DataReady ready) {
            SendPaletteSkin();
        }

        public void SendPaletteSkin() {
            if (Ctx.Client != null && Ctx.Client.PlayerInfo != null) {
                if (ModuleSettings.cNetSyncMode == 0|| ModuleSettings.cNetSyncMode == 1) {
                    //Logger.Log(LogLevel.Info, "EeveeSkin", $"Sending updated DataPlayerEeveeSkin!");
                    EeveeConfig config = EeveeModule.PlayerConfig;
                    Ctx.Client.Send(new DataPlayerEeveeSkin(Ctx.Client.PlayerInfo, config));
                }


            }
        }
    }
    public class DataPlayerEeveeSkin : DataType<DataPlayerEeveeSkin> {
        public EeveeConfig Config;
        public DataPlayerInfo Player;

        static DataPlayerEeveeSkin() { DataID = "Eeveeskin_skinconfig_" + EeveeModule.version; }
        public DataPlayerEeveeSkin() { }
        public DataPlayerEeveeSkin(DataPlayerInfo player, EeveeConfig config) {
            this.Player = player;
            this.Config = config;
        }

        public override MetaType[] GenerateMeta(DataContext ctx) => new MetaType[] {
            new MetaPlayerPrivateState(Player),
            new MetaBoundRef(DataType<DataPlayerInfo>.DataID, Player?.ID ?? uint.MaxValue, true)
        };

        public override void FixupMeta(DataContext ctx) {
            Player = Get<MetaPlayerPrivateState>(ctx);
            Get<MetaBoundRef>(ctx).ID = Player?.ID ?? uint.MaxValue;
        }

        protected override void Read(CelesteNetBinaryReader reader) {
            bool tmp = reader.ReadBoolean();
            if (tmp) {
                int tmpdash = reader.Read7BitEncodedInt();
                SkinPalette tmp_palette = new SkinPalette();
                tmp_palette.ears1 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.ears2 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.ears3 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.hair = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.fluff1 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.fluff2 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.tail1 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.tail2 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.tail3 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.eyes = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.face1 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.face2 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.frontPaw1 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.frontPaw2 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.backPaw1 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.backPaw2 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.frontPaw3 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.frontPaw4 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.backPaw3 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.backPaw4 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.body1 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.body2 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.tail4 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.tail5 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.body3 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.body4 = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.dash = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.outline = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                tmp_palette.mouth = new List<Color>() { reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA(), reader.ReadColorNoA() };
                Config = new EeveeConfig {
                    Enabled = tmp,
                    Dash = tmpdash,
                    palette = tmp_palette,

                };
            } else {
                Config = new EeveeConfig {
                    Enabled = tmp,
                    Dash = 1,
                    palette = null,
                };
            }
        }

        protected override void Write(CelesteNetBinaryWriter writer) {
            writer.Write(Config.Enabled);
            if (Config.Enabled) {
                writer.Write7BitEncodedInt(Config.Dash);
                writer.WriteNoA(Config.palette.ears1[0]); writer.WriteNoA(Config.palette.ears1[1]); writer.WriteNoA(Config.palette.ears1[2]); writer.WriteNoA(Config.palette.ears1[3]); writer.WriteNoA(Config.palette.ears1[4]);
                writer.WriteNoA(Config.palette.ears2[0]); writer.WriteNoA(Config.palette.ears2[1]); writer.WriteNoA(Config.palette.ears2[2]); writer.WriteNoA(Config.palette.ears2[3]); writer.WriteNoA(Config.palette.ears2[4]);
                writer.WriteNoA(Config.palette.ears3[0]); writer.WriteNoA(Config.palette.ears3[1]); writer.WriteNoA(Config.palette.ears3[2]); writer.WriteNoA(Config.palette.ears3[3]); writer.WriteNoA(Config.palette.ears3[4]);
                writer.WriteNoA(Config.palette.hair[0]); writer.WriteNoA(Config.palette.hair[1]); writer.WriteNoA(Config.palette.hair[2]); writer.WriteNoA(Config.palette.hair[3]); writer.WriteNoA(Config.palette.hair[4]);
                writer.WriteNoA(Config.palette.fluff1[0]); writer.WriteNoA(Config.palette.fluff1[1]); writer.WriteNoA(Config.palette.fluff1[2]); writer.WriteNoA(Config.palette.fluff1[3]); writer.WriteNoA(Config.palette.fluff1[4]);
                writer.WriteNoA(Config.palette.fluff2[0]); writer.WriteNoA(Config.palette.fluff2[1]); writer.WriteNoA(Config.palette.fluff2[2]); writer.WriteNoA(Config.palette.fluff2[3]); writer.WriteNoA(Config.palette.fluff2[4]);
                writer.WriteNoA(Config.palette.tail1[0]); writer.WriteNoA(Config.palette.tail1[1]); writer.WriteNoA(Config.palette.tail1[2]); writer.WriteNoA(Config.palette.tail1[3]); writer.WriteNoA(Config.palette.tail1[4]);
                writer.WriteNoA(Config.palette.tail2[0]); writer.WriteNoA(Config.palette.tail2[1]); writer.WriteNoA(Config.palette.tail2[2]); writer.WriteNoA(Config.palette.tail2[3]); writer.WriteNoA(Config.palette.tail2[4]);
                writer.WriteNoA(Config.palette.tail3[0]); writer.WriteNoA(Config.palette.tail3[1]); writer.WriteNoA(Config.palette.tail3[2]); writer.WriteNoA(Config.palette.tail3[3]); writer.WriteNoA(Config.palette.tail3[4]);
                writer.WriteNoA(Config.palette.eyes[0]); writer.WriteNoA(Config.palette.eyes[1]); writer.WriteNoA(Config.palette.eyes[2]); writer.WriteNoA(Config.palette.eyes[3]); writer.WriteNoA(Config.palette.eyes[4]);
                writer.WriteNoA(Config.palette.face1[0]); writer.WriteNoA(Config.palette.face1[1]); writer.WriteNoA(Config.palette.face1[2]); writer.WriteNoA(Config.palette.face1[3]); writer.WriteNoA(Config.palette.face1[4]);
                writer.WriteNoA(Config.palette.face2[0]); writer.WriteNoA(Config.palette.face2[1]); writer.WriteNoA(Config.palette.face2[2]); writer.WriteNoA(Config.palette.face2[3]); writer.WriteNoA(Config.palette.face2[4]);
                writer.WriteNoA(Config.palette.frontPaw1[0]); writer.WriteNoA(Config.palette.frontPaw1[1]); writer.WriteNoA(Config.palette.frontPaw1[2]); writer.WriteNoA(Config.palette.frontPaw1[3]); writer.WriteNoA(Config.palette.frontPaw1[4]);
                writer.WriteNoA(Config.palette.frontPaw2[0]); writer.WriteNoA(Config.palette.frontPaw2[1]); writer.WriteNoA(Config.palette.frontPaw2[2]); writer.WriteNoA(Config.palette.frontPaw2[3]); writer.WriteNoA(Config.palette.frontPaw2[4]);
                writer.WriteNoA(Config.palette.backPaw1[0]); writer.WriteNoA(Config.palette.backPaw1[1]); writer.WriteNoA(Config.palette.backPaw1[2]); writer.WriteNoA(Config.palette.backPaw1[3]); writer.WriteNoA(Config.palette.backPaw1[4]);
                writer.WriteNoA(Config.palette.backPaw2[0]); writer.WriteNoA(Config.palette.backPaw2[1]); writer.WriteNoA(Config.palette.backPaw2[2]); writer.WriteNoA(Config.palette.backPaw2[3]); writer.WriteNoA(Config.palette.backPaw2[4]);
                writer.WriteNoA(Config.palette.frontPaw3[0]); writer.WriteNoA(Config.palette.frontPaw3[1]); writer.WriteNoA(Config.palette.frontPaw3[2]); writer.WriteNoA(Config.palette.frontPaw3[3]); writer.WriteNoA(Config.palette.frontPaw3[4]);
                writer.WriteNoA(Config.palette.frontPaw4[0]); writer.WriteNoA(Config.palette.frontPaw4[1]); writer.WriteNoA(Config.palette.frontPaw4[2]); writer.WriteNoA(Config.palette.frontPaw4[3]); writer.WriteNoA(Config.palette.frontPaw4[4]);
                writer.WriteNoA(Config.palette.backPaw3[0]); writer.WriteNoA(Config.palette.backPaw3[1]); writer.WriteNoA(Config.palette.backPaw3[2]); writer.WriteNoA(Config.palette.backPaw3[3]); writer.WriteNoA(Config.palette.backPaw3[4]);
                writer.WriteNoA(Config.palette.backPaw4[0]); writer.WriteNoA(Config.palette.backPaw4[1]); writer.WriteNoA(Config.palette.backPaw4[2]); writer.WriteNoA(Config.palette.backPaw4[3]); writer.WriteNoA(Config.palette.backPaw4[4]);
                writer.WriteNoA(Config.palette.body1[0]); writer.WriteNoA(Config.palette.body1[1]); writer.WriteNoA(Config.palette.body1[2]); writer.WriteNoA(Config.palette.body1[3]); writer.WriteNoA(Config.palette.body1[4]);
                writer.WriteNoA(Config.palette.body2[0]); writer.WriteNoA(Config.palette.body2[1]); writer.WriteNoA(Config.palette.body2[2]); writer.WriteNoA(Config.palette.body2[3]); writer.WriteNoA(Config.palette.body2[4]);
                writer.WriteNoA(Config.palette.tail4[0]); writer.WriteNoA(Config.palette.tail4[1]); writer.WriteNoA(Config.palette.tail4[2]); writer.WriteNoA(Config.palette.tail4[3]); writer.WriteNoA(Config.palette.tail4[4]);
                writer.WriteNoA(Config.palette.tail5[0]); writer.WriteNoA(Config.palette.tail5[1]); writer.WriteNoA(Config.palette.tail5[2]); writer.WriteNoA(Config.palette.tail5[3]); writer.WriteNoA(Config.palette.tail5[4]);
                writer.WriteNoA(Config.palette.body3[0]); writer.WriteNoA(Config.palette.body3[1]); writer.WriteNoA(Config.palette.body3[2]); writer.WriteNoA(Config.palette.body3[3]); writer.WriteNoA(Config.palette.body3[4]);
                writer.WriteNoA(Config.palette.body4[0]); writer.WriteNoA(Config.palette.body4[1]); writer.WriteNoA(Config.palette.body4[2]); writer.WriteNoA(Config.palette.body4[3]); writer.WriteNoA(Config.palette.body4[4]);
                writer.WriteNoA(Config.palette.dash[0]); writer.WriteNoA(Config.palette.dash[1]); writer.WriteNoA(Config.palette.dash[2]); writer.WriteNoA(Config.palette.dash[3]); writer.WriteNoA(Config.palette.dash[4]);
                writer.WriteNoA(Config.palette.outline[0]); writer.WriteNoA(Config.palette.outline[1]); writer.WriteNoA(Config.palette.outline[2]); writer.WriteNoA(Config.palette.outline[3]); writer.WriteNoA(Config.palette.outline[4]);
                writer.WriteNoA(Config.palette.mouth[0]); writer.WriteNoA(Config.palette.mouth[1]); writer.WriteNoA(Config.palette.mouth[2]); writer.WriteNoA(Config.palette.mouth[3]); writer.WriteNoA(Config.palette.mouth[4]);
            }
        }
    }
}
