﻿using Newtonsoft.Json;
using System.Linq;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Minicopter Licence Plate", "The Friendly Chap", "1.2.0")]
    [Description("Spawn a licence plate (Small Wooden Board) at the back of the minicopter, with optional permissions.")]
    class MiniPlate : RustPlugin
    {
        const string PlatePrefab = "assets/prefabs/deployable/signs/sign.small.wood.prefab";
        private static readonly Vector3 PlatePosition = new Vector3(0.0f, 0.20f, -0.85f);
        private static readonly Quaternion PlateRotation = Quaternion.Euler(180, 0, 180);
        private const string PLATE_MARKER = "[MiniPlateTag]";

        private ConfigData configData;

        class ConfigData
        {
            [JsonProperty(PropertyName = "Use Permissions")]
            public bool UsePermissions = false;

            [JsonProperty(PropertyName = "Debug")]
            public bool Debug = false;
        }

        void Init()
        {
            ShowLogo();
            permission.RegisterPermission("miniplate.use", this);

            if (!LoadConfigVariables())
            {
                Puts("Config file issue detected. Please delete the file or check the syntax and fix it.");
            }
        }

        protected override void LoadDefaultConfig()
        {
            Puts("Creating new config file.");
            configData = new ConfigData();
            SaveConfig(configData);
        }

        private bool LoadConfigVariables()
        {
            try
            {
                configData = Config.ReadObject<ConfigData>();
            }
            catch
            {
                return false;
            }
            SaveConfig(configData);
            return true;
        }

        void SaveConfig(ConfigData config)
        {
            Config.WriteObject(config, true);
        }

        private void OnServerInitialized()
        {
            FindMinicopters();
        }

        void FindMinicopters()
        {
            foreach (var entity in BaseNetworkable.serverEntities.OfType<Minicopter>())
            {
                if (entity == null || entity.IsDestroyed) continue;

                if (!HasLicensePlate(entity))
                {
                    if (!configData.UsePermissions || permission.UserHasPermission(entity.OwnerID.ToString(), "miniplate.use"))
                    {
                        AttachLicensePlate(entity);
                    }
                }
            }
        }

        void OnEntitySpawned(BaseNetworkable entity)
        {
            var mini = entity as Minicopter;
            if (mini == null || mini.IsDestroyed) return;

            if (configData.UsePermissions)
            {
                if (!permission.UserHasPermission(mini.OwnerID.ToString(), "miniplate.use"))
                    return;
            }

            if (HasLicensePlate(mini))
                return;

            AttachLicensePlate(mini);
        }

        private bool HasLicensePlate(Minicopter mini)
        {
            if (mini == null || mini.IsDestroyed || mini.children == null)
                return false;

            foreach (var child in mini.children)
            {
                if (child == null || child.IsDestroyed)
                    continue;

                if (child.name != null && child.name.Contains(PLATE_MARKER))
                    return true;
            }

            return false;
        }

        void AttachLicensePlate(BaseVehicle vehicle)
        {
            if (vehicle == null || vehicle.IsDestroyed) return;

            var plate = CreateLicensePlate(vehicle, PlatePosition);
            if (plate != null && !string.IsNullOrEmpty(plate.name))
            {
                plate.name = plate.name + PLATE_MARKER;
            }
        }

        BaseEntity CreateLicensePlate(BaseVehicle vehicle, Vector3 localPosition)
        {
            var entity = GameManager.server.CreateEntity(PlatePrefab, vehicle.transform.position, PlateRotation);
            if (entity == null) return null;

            DestroyUnnecessaryComponents(entity);
            entity.SetParent(vehicle);
            entity.transform.localPosition = localPosition;
            entity.Spawn();

            if (configData.Debug)
                Puts($"Attached license plate to minicopter {vehicle.net?.ID}");

            return entity;
        }

        void DestroyUnnecessaryComponents(BaseEntity entity)
        {
            if (entity == null) return;

            if (configData.Debug) Puts($"Cleaning components on {entity.ShortPrefabName} ({entity.net?.ID})");

            var groundComp = entity.GetComponent<DestroyOnGroundMissing>();
            if (groundComp != null) UnityEngine.Object.DestroyImmediate(groundComp);

            var groundWatch = entity.GetComponent<GroundWatch>();
            if (groundWatch != null) UnityEngine.Object.DestroyImmediate(groundWatch);

            var decayComp = entity.GetComponent<DeployableDecay>();
            if (decayComp != null) UnityEngine.Object.DestroyImmediate(decayComp);

            var meshColliders = entity.GetComponentsInChildren<MeshCollider>();
            foreach (var meshCollider in meshColliders)
            {
                UnityEngine.Object.DestroyImmediate(meshCollider);
            }

            if (!entity.gameObject.GetComponent<BoxCollider>())
            {
                var box = entity.gameObject.AddComponent<BoxCollider>();
                box.size = new Vector3(0.8f, 0.4f, 0.05f); // reasonable default for small sign
                box.center = Vector3.zero;
            }
        }

        private void ShowLogo()
        {
            Puts(" _______ __               _______        __                 __ __             ______ __");
            Puts("|_     _|  |--.-----.    |    ___|.----.|__|.-----.-----.--|  |  |.--.--.    |      |  |--.---.-.-----.");
            Puts("  |   | |     |  -__|    |    ___||   _||  ||  -__|     |  _  |  ||  |  |    |   ---|     |  _  |  _  |");
            Puts("  |___| |__|__|_____|    |___|    |__|  |__||_____|__|__|_____|__||___  |    |______|__|__|___._|   __|");
            Puts("  MiniPlate.cs v1.2.0                twitch.tv/the_friendly_chap  |_____|                       |__|");
        }
    }
}