using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public delegate void SewPointCollected(GameObject obj);
public delegate void HoleComplete(GameObject obj);

public class HoleBehaviour : MonoBehaviour
{
    public GameObject sewPointPrefab;
    public float minRadius = 0.4f;
    public event HoleComplete holeCompleteHandler;
    Vector2 renderBounds = Vector2.one;
    private SpriteRenderer _renderer;
    public Sprite completedSprite;

    public ClothType targetCloth;

    public bool generateOnStart = true;

    private List<GameObject> WinPoints = new List<GameObject>();

    private int numSewLeft;

    public AudioSource m_AudioPlayer;
    public AudioClip m_CollectedSound;
    public AudioClip m_FailCollectSound;
    public ParticleSystem m_PS;

    // Start is called before the first frame update
    void Start()
    {
        _renderer = gameObject.GetComponent<SpriteRenderer>();
        renderBounds = _renderer.bounds.size;
        targetCloth  = UnityEngine.Object.FindObjectOfType<GameController>().RequestForClothColor();

        if (generateOnStart) GenerateSewPoints();

        if (_renderer) _renderer.color = ColourManager.instance.GetClothColorFromEnum(targetCloth);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    void GenerateSewPoints()
    {
        PoissonDiscSampler sampler = new PoissonDiscSampler(renderBounds.x,renderBounds.y,minRadius);
        foreach (Vector2 sample in sampler.Samples())
        {
            Vector3 spawnPoint = transform.position + (Vector3)sample - ((Vector3)renderBounds/2.0f);
            GameObject newSewPoint = Instantiate(sewPointPrefab);
            newSewPoint.transform.position = spawnPoint;
            newSewPoint.transform.parent   = transform;
            WinSewPoints sewPointComp = newSewPoint.GetComponent<WinSewPoints>();
            sewPointComp.SewPointHandler += SewPointCollectedCallback;
            WinPoints.Add(newSewPoint);
        }

        Debug.Log(gameObject.name + " is generating " + WinPoints.Count + " SewPoints");
    }

    void SewPointCollectedCallback(GameObject obj)
    {
        Debug.Log("Sew point collected callback");

        MouseController mouse = GameObject.FindObjectOfType<MouseController>();
        if (mouse && mouse.m_CurrentCloth){
            GrabbableCloth cloth = mouse.m_CurrentCloth.GetComponent<GrabbableCloth>();
            if (cloth.m_ClothType != targetCloth)
            {
                ErrorCallback(obj);
                return;
            }
        }

        m_AudioPlayer.clip = m_CollectedSound;
        m_AudioPlayer.Play();
        WinPoints.Remove(obj);
        
        Destroy(obj);

        if (WinPoints.Count == 0)
        {
            HoleCompleteCallback();
        }
    }

    void ErrorCallback(GameObject obj)
    {
        Debug.Log(obj.name + "is touched but the player has the wrong cloth!");
    }


    void HoleCompleteCallback()
    {
        Debug.Log("Hole is complete!");
        _renderer.sprite = completedSprite;
        ColourManager colourManager = ColourManager.instance;
        _renderer.color = colourManager.GetClothColorFromEnum(targetCloth);
        m_PS.Emit(50);

        MouseController mouse = GameObject.FindObjectOfType<MouseController>();
        if (mouse && mouse.m_CurrentCloth){
            GrabbableCloth cloth = mouse.m_CurrentCloth.GetComponent<GrabbableCloth>();
            mouse.m_CurrentCloth = null;
            cloth.DestroyCloth();
        }
        if (holeCompleteHandler != null)
        {
            holeCompleteHandler(gameObject);
        }
    }
}
