using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class Bootstrap : MonoBehaviour
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
    private static void Init()
    {
        if (FindObjectOfType<Bootstrap>() != null) return;

        var bootstrapObject = new GameObject("Bootstrap");
        bootstrapObject.AddComponent<Bootstrap>();
    }

    private void Awake()
    {
        if (FindObjectsOfType<Bootstrap>().Length > 1)
        {
            Destroy(gameObject);
            return;
        }

        CreateCamera();
        CreateEventSystem();
        CreateAudioManager();
        CreateImageGalleryManager();
        CreateGameManager();
        CreatePlayer();
        CreateUi();
    }

    private static void CreateImageGalleryManager()
    {
        if (FindObjectOfType<ImageGalleryManager>() != null) return;

        var galleryManagerObject = new GameObject("ImageGalleryManager");
        galleryManagerObject.AddComponent<ImageGalleryManager>();
    }

    private static void CreateCamera()
    {
        if (Camera.main != null) return;

        var cameraObject = new GameObject("Main Camera");
        var camera = cameraObject.AddComponent<Camera>();
        camera.orthographic = true;
        camera.orthographicSize = 5f;
        camera.backgroundColor = Color.black;
        cameraObject.transform.position = new Vector3(0f, 0f, -10f);
    }

    private static void CreateEventSystem()
    {
        if (FindObjectOfType<EventSystem>() != null) return;

        var eventSystemObject = new GameObject("EventSystem");
        eventSystemObject.AddComponent<EventSystem>();
        eventSystemObject.AddComponent<StandaloneInputModule>();
    }

    private static void CreateAudioManager()
    {
        if (FindObjectOfType<AudioManager>() != null) return;

        var audioManagerObject = new GameObject("AudioManager");
        audioManagerObject.AddComponent<AudioManager>();
    }

    private void CreateGameManager()
    {
        if (FindObjectOfType<GameManager>() != null) return;

        var gameManagerObject = new GameObject("GameManager");
        gameManagerObject.AddComponent<GameManager>();
    }

    private void CreatePlayer()
    {
        if (FindObjectOfType<PlayerController>() != null) return;

        var playerObject = new GameObject("Player");
        playerObject.transform.position = new Vector3(0f, -3.8f, 0f);
        playerObject.tag = "Player";

        var renderer = playerObject.AddComponent<SpriteRenderer>();
        renderer.color = Color.cyan;
        renderer.drawMode = SpriteDrawMode.Simple;
        renderer.sprite = CreatePlayerSprite();

        var collider = playerObject.AddComponent<BoxCollider2D>();
        collider.isTrigger = true;

        var rb = playerObject.AddComponent<Rigidbody2D>();
        rb.gravityScale = 0f;
        rb.bodyType = RigidbodyType2D.Kinematic;

        var player = playerObject.AddComponent<PlayerController>();
        player.bulletPrefab = CreateBulletPrefab();
    }

    private void CreateUi()
    {
        var canvasObject = GameObject.Find("Canvas");
        if (canvasObject == null)
        {
            canvasObject = new GameObject("Canvas");
            var canvas = canvasObject.AddComponent<Canvas>();
            canvas.renderMode = RenderMode.ScreenSpaceOverlay;
            canvasObject.AddComponent<CanvasScaler>();
            canvasObject.AddComponent<GraphicRaycaster>();
        }

        var gameManager = FindObjectOfType<GameManager>();
        if (gameManager == null) return;

        gameManager.scoreText = CreateTopLeftText(canvasObject.transform, "ScoreText", new Vector2(20f, -20f), "Score: 0", 28, Color.white);
        gameManager.livesText = CreateTopRightText(canvasObject.transform, "LivesText", new Vector2(-20f, -20f), "Lives: 3", 28, Color.white);
        gameManager.waveText = CreateTopLeftText(canvasObject.transform, "WaveText", new Vector2(20f, -58f), "Wave: 1", 24, new Color(0.8f, 0.8f, 0.8f, 1f));
        gameManager.comboText = CreateTopLeftText(canvasObject.transform, "ComboText", new Vector2(20f, -88f), "Combo x1", 22, new Color(0.9f, 0.65f, 0.25f, 1f));
        gameManager.highScoreText = CreateTopLeftText(canvasObject.transform, "HighScoreText", new Vector2(20f, -116f), "Best: 0", 22, new Color(0.75f, 0.9f, 1f, 1f));
        gameManager.statusText = CreateTopCenterText(canvasObject.transform, "StatusText", new Vector2(0f, -148f), "Tap start to begin", 24, Color.white);

        gameManager.startPanel = CreatePanel(canvasObject.transform, "StartPanel");
        gameManager.gameOverPanel = CreatePanel(canvasObject.transform, "GameOverPanel");

        CreateCenteredText(gameManager.startPanel.transform, "StartTitle", "Face Invaders", 42, Color.white, new Vector2(0f, 90f));
        CreateCenteredText(gameManager.startPanel.transform, "StartSubtitle", "Protect the city from your friends' faces", 22, new Color(0.85f, 0.85f, 0.85f, 1f), new Vector2(0f, 35f));

        var galleryPanel = CreatePanel(canvasObject.transform, "GalleryPanel");
        CreateCenteredText(galleryPanel.transform, "GalleryTitle", "Select Face Images", 36, Color.white, new Vector2(0f, 100f));
        var faceCountText = CreateCenteredText(galleryPanel.transform, "FaceCountText", "Faces loaded: 0", 24, new Color(0.8f, 0.8f, 0.8f, 1f), new Vector2(0f, 40f));

        var pickButton = CreateCenteredButton(galleryPanel.transform, "PickImageButton", "Pick from gallery", new Vector2(0f, -20f), null);
        var clearButton = CreateCenteredButton(galleryPanel.transform, "ClearButton", "Clear all images", new Vector2(0f, -100f), null);
        var playButton = CreateCenteredButton(galleryPanel.transform, "PlayButton", "Play game", new Vector2(0f, -180f), null);

        var galleryMenu = galleryPanel.AddComponent<GalleryMenu>();
        galleryMenu.galleryPanel = galleryPanel;
        galleryMenu.faceCountText = faceCountText;
        galleryMenu.pickImageButton = pickButton;
        galleryMenu.clearButton = clearButton;
        galleryMenu.playButton = playButton;

        CreateCenteredButton(gameManager.startPanel.transform, "StartButton", "Configure faces", new Vector2(0f, 0f), () => 
        {
            gameManager.startPanel.SetActive(false);
            galleryPanel.SetActive(true);
        });

        CreateCenteredText(gameManager.gameOverPanel.transform, "GameOverTitle", "Game Over", 42, Color.white, new Vector2(0f, 90f));
        CreateCenteredText(gameManager.gameOverPanel.transform, "GameOverSubtitle", "You made it to the end of the wave", 22, new Color(0.85f, 0.85f, 0.85f, 1f), new Vector2(0f, 35f));
        CreateCenteredButton(gameManager.gameOverPanel.transform, "RestartButton", "Play again", new Vector2(0f, -50f), () => gameManager.StartNewGame());

        CreateButton(canvasObject.transform, "LeftButton", "Left", TouchButton.ButtonType.Left);
        CreateButton(canvasObject.transform, "RightButton", "Right", TouchButton.ButtonType.Right);
        CreateButton(canvasObject.transform, "FireButton", "Fire", TouchButton.ButtonType.Fire);
    }

    private static Button CreateCenteredButton(Transform parent, string name, string label, Vector2 position, UnityEngine.Events.UnityAction onClick)
    {
        var buttonObject = GameObject.Find(name);
        if (buttonObject == null)
        {
            buttonObject = new GameObject(name);
            buttonObject.transform.SetParent(parent, false);

            var image = buttonObject.AddComponent<Image>();
            image.color = new Color(0.2f, 0.5f, 1f, 1f);
            var button = buttonObject.AddComponent<Button>();
            button.targetGraphic = image;
            if (onClick != null)
            {
                button.onClick.AddListener(onClick);
            }

            var textObject = new GameObject(name + "Text");
            textObject.transform.SetParent(buttonObject.transform, false);
            var text = textObject.AddComponent<Text>();
            text.text = label;
            text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
            text.color = Color.white;
            text.alignment = TextAnchor.MiddleCenter;
            text.fontSize = 24;

            var rect = buttonObject.GetComponent<RectTransform>();
            rect.sizeDelta = new Vector2(220f, 64f);
            rect.anchorMin = new Vector2(0.5f, 0.5f);
            rect.anchorMax = new Vector2(0.5f, 0.5f);
            rect.anchoredPosition = position;

            var textRect = text.GetComponent<RectTransform>();
            textRect.anchorMin = Vector2.zero;
            textRect.anchorMax = Vector2.one;
            textRect.offsetMin = Vector2.zero;
            textRect.offsetMax = Vector2.zero;

            return button;
        }

        return buttonObject.GetComponent<Button>();
    }

    private static Text CreateTopLeftText(Transform parent, string name, Vector2 position, string content, int fontSize, Color color)
    {
        var textObject = GameObject.Find(name);
        if (textObject == null)
        {
            textObject = new GameObject(name);
            textObject.transform.SetParent(parent, false);
        }

        var text = textObject.GetComponent<Text>();
        if (text == null)
        {
            text = textObject.AddComponent<Text>();
        }

        text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
        text.text = content;
        text.color = color;
        text.fontSize = fontSize;
        text.alignment = TextAnchor.UpperLeft;

        var rect = text.GetComponent<RectTransform>();
        rect.anchorMin = new Vector2(0f, 1f);
        rect.anchorMax = new Vector2(0f, 1f);
        rect.anchoredPosition = position;
        return text;
    }

    private static Text CreateTopRightText(Transform parent, string name, Vector2 position, string content, int fontSize, Color color)
    {
        var textObject = GameObject.Find(name);
        if (textObject == null)
        {
            textObject = new GameObject(name);
            textObject.transform.SetParent(parent, false);
        }

        var text = textObject.GetComponent<Text>();
        if (text == null)
        {
            text = textObject.AddComponent<Text>();
        }

        text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
        text.text = content;
        text.color = color;
        text.fontSize = fontSize;
        text.alignment = TextAnchor.UpperRight;

        var rect = text.GetComponent<RectTransform>();
        rect.anchorMin = new Vector2(1f, 1f);
        rect.anchorMax = new Vector2(1f, 1f);
        rect.anchoredPosition = position;
        return text;
    }

    private static Text CreateTopCenterText(Transform parent, string name, Vector2 position, string content, int fontSize, Color color)
    {
        var textObject = GameObject.Find(name);
        if (textObject == null)
        {
            textObject = new GameObject(name);
            textObject.transform.SetParent(parent, false);
        }

        var text = textObject.GetComponent<Text>();
        if (text == null)
        {
            text = textObject.AddComponent<Text>();
        }

        text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
        text.text = content;
        text.color = color;
        text.fontSize = fontSize;
        text.alignment = TextAnchor.UpperCenter;

        var rect = text.GetComponent<RectTransform>();
        rect.anchorMin = new Vector2(0.5f, 1f);
        rect.anchorMax = new Vector2(0.5f, 1f);
        rect.anchoredPosition = position;
        return text;
    }

    private static Text CreateCenteredText(Transform parent, string name, string content, int fontSize, Color color, Vector2 position)
    {
        var textObject = GameObject.Find(name);
        if (textObject == null)
        {
            textObject = new GameObject(name);
            textObject.transform.SetParent(parent, false);
        }

        var text = textObject.GetComponent<Text>();
        if (text == null)
        {
            text = textObject.AddComponent<Text>();
        }

        text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
        text.text = content;
        text.color = color;
        text.fontSize = fontSize;
        text.alignment = TextAnchor.MiddleCenter;

        var rect = text.GetComponent<RectTransform>();
        rect.anchorMin = new Vector2(0.5f, 0.5f);
        rect.anchorMax = new Vector2(0.5f, 0.5f);
        rect.anchoredPosition = position;
        return text;
    }

    private static GameObject CreatePanel(Transform parent, string name)
    {
        var panelObject = GameObject.Find(name);
        if (panelObject == null)
        {
            panelObject = new GameObject(name);
            panelObject.transform.SetParent(parent, false);

            var image = panelObject.AddComponent<Image>();
            image.color = new Color(0f, 0f, 0f, 0.75f);

            var rect = panelObject.GetComponent<RectTransform>();
            rect.anchorMin = Vector2.zero;
            rect.anchorMax = Vector2.one;
            rect.anchoredPosition = Vector2.zero;
            rect.sizeDelta = Vector2.zero;
        }

        return panelObject;
    }

    private static void CreateButton(Transform parent, string name, string label, UnityEngine.Events.UnityAction onClick)
    {
        var buttonObject = GameObject.Find(name);
        if (buttonObject == null)
        {
            buttonObject = new GameObject(name);
            buttonObject.transform.SetParent(parent, false);

            var image = buttonObject.AddComponent<Image>();
            image.color = new Color(0.2f, 0.5f, 1f, 1f);
            var button = buttonObject.AddComponent<Button>();
            button.targetGraphic = image;
            if (onClick != null)
            {
                button.onClick.AddListener(onClick);
            }

            var textObject = new GameObject(name + "Text");
            textObject.transform.SetParent(buttonObject.transform, false);
            var text = textObject.AddComponent<Text>();
            text.text = label;
            text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
            text.color = Color.white;
            text.alignment = TextAnchor.MiddleCenter;
            text.fontSize = 24;

            var rect = buttonObject.GetComponent<RectTransform>();
            rect.sizeDelta = new Vector2(220f, 64f);
            rect.anchorMin = new Vector2(0.5f, 0.5f);
            rect.anchorMax = new Vector2(0.5f, 0.5f);
            rect.anchoredPosition = Vector2.zero;

            var textRect = text.GetComponent<RectTransform>();
            textRect.anchorMin = Vector2.zero;
            textRect.anchorMax = Vector2.one;
            textRect.offsetMin = Vector2.zero;
            textRect.offsetMax = Vector2.zero;
        }
    }

    private static void CreateButton(Transform parent, string name, string label, TouchButton.ButtonType buttonType)
    {
        if (GameObject.Find(name) != null) return;

        var buttonObject = new GameObject(name);
        buttonObject.transform.SetParent(parent, false);

        var image = buttonObject.AddComponent<Image>();
        image.color = new Color(1f, 1f, 1f, 0.25f);
        var rect = buttonObject.GetComponent<RectTransform>();
        rect.sizeDelta = new Vector2(120f, 70f);
        rect.anchorMin = new Vector2(0.5f, 0f);
        rect.anchorMax = new Vector2(0.5f, 0f);
        rect.anchoredPosition = buttonType == TouchButton.ButtonType.Left ? new Vector2(-90f, 60f) : buttonType == TouchButton.ButtonType.Right ? new Vector2(90f, 60f) : new Vector2(0f, 60f);

        var textObject = new GameObject(name + "Text");
        textObject.transform.SetParent(buttonObject.transform, false);
        var text = textObject.AddComponent<Text>();
        text.text = label;
        text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
        text.color = Color.white;
        text.alignment = TextAnchor.MiddleCenter;
        text.resizeTextForBestFit = true;
        var textRect = text.GetComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.offsetMin = Vector2.zero;
        textRect.offsetMax = Vector2.zero;

        var button = buttonObject.AddComponent<Button>();
        button.targetGraphic = image;

        var touchButton = buttonObject.AddComponent<TouchButton>();
        touchButton.buttonType = buttonType;
    }

    private static Sprite CreatePlayerSprite()
    {
        var texture = new Texture2D(64, 64);
        var pixels = new Color[64 * 64];
        for (int i = 0; i < pixels.Length; i++)
        {
            pixels[i] = Color.cyan;
        }

        texture.SetPixels(pixels);
        texture.Apply();
        return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f), 100f);
    }

    private static GameObject CreateBulletPrefab()
    {
        var bullet = new GameObject("BulletPrefab");
        bullet.AddComponent<SpriteRenderer>().color = Color.yellow;
        bullet.AddComponent<BoxCollider2D>();
        bullet.AddComponent<Rigidbody2D>();
        bullet.SetActive(false);
        return bullet;
    }
}
