using UnityEngine;
using System.Collections.Generic;

public class PieceGrabbingHandler : MonoBehaviour {

	// Use this for initialization
	void Start () {
    }

    private bool Dragging = false;
    private Vector3 DragOrigin = Vector3.zero;
    private List<GameObject> draggingList = null;
    private List<Vector3> draggingOriginPositions = new List<Vector3>();

    public GameObject[] ShiftIndicators = null;
    public Sprite[] shiftIndicatorSprites = null;
    public AudioClip noMatchFoundSound = null;

    private void SetShiftIndicator(int ShiftAmount)
    {
        foreach (GameObject indicator in ShiftIndicators)
        {
            if (ShiftAmount == 0)
            {
                indicator.SetActive(false);
            }
            else
            {
                indicator.SetActive(true);
                if (ShiftAmount - 1 < shiftIndicatorSprites.Length)
                    indicator.GetComponent<SpriteRenderer>().sprite = shiftIndicatorSprites[ShiftAmount - 1];
            }
        }
    }

    public enum Direction
    {
        None,
        Vertical,
        Horizontal
    }

    private Direction dragDirection = Direction.None;

    public GameObject HorizontalHighlight = null;
    public GameObject VerticalHighlight = null;

    private void InitiateHorizontalDrag(Vector3 currentDragLocation)
    {
        dragDirection = Direction.Horizontal;

        // Get a list of all the shapes in the drag row
        draggingList = gameObject.GetComponent<ShapeManager>().GetAllShapesInWorldPositionRow(currentDragLocation);
        draggingOriginPositions.Clear();
        foreach (GameObject o in draggingList)
        {
            draggingOriginPositions.Add(o.transform.position);
            o.GetComponent<ShapeInfo>().beingDragged = true;
        }
    }

    private void InitiateVerticalDrag(Vector3 currentDragLocation)
    {
        dragDirection = Direction.Vertical;

        // Get a list of all the shapes in the drag row
        draggingList = gameObject.GetComponent<ShapeManager>().GetAllShapesInWorldPositionColumn(currentDragLocation);
        draggingOriginPositions.Clear();
        foreach (GameObject o in draggingList)
        {
            draggingOriginPositions.Add(o.transform.position);
            o.GetComponent<ShapeInfo>().beingDragged = true;
        }
    }


    // Update is called once per frame
    void Update () {
        Vector3 currentDragPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);

        ShapeManager sm = gameObject.GetComponent<ShapeManager>();

        if (!Dragging)
        {
            if (sm.AvailableForDragging && !GameManager.Instance.TimeKeeper.TimeOver)
            {
                if (Input.GetMouseButtonDown(0))
                {
                    // Start dragging
                    Dragging = true;
                    GameManager.Instance.ScoreAccumulator.ResetAccumulator();

                    // Figure out what row or column we're dragging
                    DragOrigin = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                    dragDirection = Direction.None;
                }
            }
        }
        else
        {
            // Figure out how far we've dragged that row
            float worldDragDeltaX = currentDragPos.x - DragOrigin.x;
            float worldDragDeltaY = currentDragPos.y - DragOrigin.y;

            int horizontalShiftCount = sm.CalculateHorizontalShiftAmountFromWorldDistance(worldDragDeltaX);
            int verticalShiftCount = sm.CalculateVerticalShiftAmountFromWorldDistance(worldDragDeltaY);

            if (dragDirection == Direction.None)
            {
                // Figure out if we're dragging horizontally or vertically
                if (Mathf.Abs(worldDragDeltaX) > 0.1f || Mathf.Abs(worldDragDeltaY) > 0.1f)
                {
                    if (Mathf.Abs(worldDragDeltaX) > Mathf.Abs(worldDragDeltaY))
                    {
                        InitiateHorizontalDrag(DragOrigin);
                    }
                    else
                    {
                        InitiateVerticalDrag(DragOrigin);
                    }
                }
            }


            // See if the player wants to stop dragging
            if (Input.GetMouseButtonUp(0))
            {
                Dragging = false;

                // Drop all the pieces off
                if (dragDirection != Direction.None)
                {
                    foreach (GameObject o in draggingList)
                    {
                        // Tell the piece it isn't being dragged anymore
                        o.GetComponent<ShapeInfo>().beingDragged = false;
                    }
                }

                int dragAmount = 0;
                if (dragDirection == Direction.Vertical)
                    dragAmount = verticalShiftCount;
                else if (dragDirection == Direction.Horizontal)
                    dragAmount = horizontalShiftCount;

                // Check to see if we would actually make any matches
                if (!sm.HasMatchingPieces())
                {
                    sm.ReturnEverybodyHome();
                    sm.SetPreviewShiftAmounts(0, 0, 0, 0);


                    dragDirection = Direction.None;

                    if ( dragAmount != 0)
                    {

                        AudioSource mySource = GetComponent<AudioSource>();
                        mySource.clip = noMatchFoundSound;
                        mySource.Play();
                    }


                }
                else
                {
                    // Announce shift
                    GameManager.Instance.Annoucer.PlaySoundForShift(dragAmount);

                    sm.SetPreviewShiftAmounts(0, 0, 0, 0);

                    if (dragDirection != Direction.None)
                    {
                        // Update the piece's position
                        if (dragDirection == Direction.Horizontal)
                        {
                            sm.ShiftRowBasedOnWorldDistance(DragOrigin, worldDragDeltaX);
                        }
                        else if (dragDirection == Direction.Vertical)
                        {
                            sm.ShiftColumnBasedOnWorldDistance(DragOrigin, worldDragDeltaY);
                        }
                        dragDirection = Direction.None;
                    }
                }
            }
            else
            {
                Bounds WrapExtents = sm.GetPlayspaceExtents();

                int previewRow = sm.GetRowForWorldPosition(DragOrigin);
                int previewRowAmount = 0;
                int previewCol = sm.GetColumnForWorldPosition(DragOrigin);
                int previewColAmount = 0;

                if (dragDirection == Direction.Horizontal)
                {

                    // Shift everything in that row over
                    for (int i = 0; i < draggingList.Count; i++)
                    {
                        Vector3 newPosition = draggingOriginPositions[i];
                        newPosition.x += worldDragDeltaX;

                        while (newPosition.x > WrapExtents.max.x)
                            newPosition.x -= WrapExtents.size.x;

                        while (newPosition.x < WrapExtents.min.x)
                            newPosition.x += WrapExtents.size.x;

                        draggingList[i].GetComponent<ShapeInfo>().visualDestinationPosition = newPosition;
                    }

                    previewRowAmount = horizontalShiftCount;
                }
                else if (dragDirection == Direction.Vertical)
                {

                    // Shift everything in the column over
                    for (int i = 0; i < draggingList.Count; i++)
                    {
                        Vector3 newPosition = draggingOriginPositions[i];
                        newPosition.y += worldDragDeltaY;

                        while (newPosition.y > WrapExtents.max.y)
                            newPosition.y -= WrapExtents.size.y;

                        while (newPosition.y < WrapExtents.min.y)
                            newPosition.y += WrapExtents.size.y;

                        draggingList[i].GetComponent<ShapeInfo>().visualDestinationPosition = newPosition;
                    }

                    previewColAmount = verticalShiftCount;
                }
                sm.SetPreviewShiftAmounts(previewCol, previewColAmount, previewRow, previewRowAmount);
            }

            // Update shift indicators
            if (Dragging && dragDirection != Direction.None)
            {
                int shiftAmount = 0;
                if (dragDirection == Direction.Horizontal)
                {
                    shiftAmount = horizontalShiftCount;
                }
                else if (dragDirection == Direction.Vertical)
                {
                    shiftAmount = verticalShiftCount;
                }

                SetShiftIndicator(Mathf.Abs(shiftAmount));
                GameManager.Instance.ScoreAccumulator.SetShiftMultiplier(GameSettings.MultipliersForShiftAmount[Mathf.Abs(shiftAmount)]);
            }
            else
            {
                SetShiftIndicator(0);
            }
        }

        // Pause deletion on the Shape Manager while we are dragging - this is to allow previewing of matches
        sm.DeletionPaused = Dragging;

        // Highlighting
        Bounds highlightBounds = sm.GetPlayspaceExtents();

        // Calculate the appropriate highlight row and column
        int highlightRow = -1;
        int highlightColumn = -1;
        if (Dragging)
        {
            highlightRow = sm.GetRowForWorldPosition(DragOrigin);
            highlightColumn = sm.GetColumnForWorldPosition(DragOrigin);
        }
        else if (highlightBounds.Contains(currentDragPos))
        {
            highlightRow = sm.GetRowForWorldPosition(currentDragPos);
            highlightColumn = sm.GetColumnForWorldPosition(currentDragPos);
        }

        // Position the highlights accordingly
        if (highlightRow != -1)
        {
            Vector3 highlightPosition = sm.GetWorldPositionForShapeLocation(0, highlightRow);
            highlightPosition.x = 0.0f;
            HorizontalHighlight.transform.position = highlightPosition;
        }

        if (highlightColumn != -1)
        {
            Vector3 highlightPosition = sm.GetWorldPositionForShapeLocation(highlightColumn, 0);
            highlightPosition.y = 0.0f;
            VerticalHighlight.transform.position = highlightPosition;
        }

        // Show or don't show them accordingly.
        if ((!Dragging || dragDirection != Direction.Vertical) && highlightRow != -1 && sm.AvailableForDragging)
        {
            HorizontalHighlight.SetActive(true);
        }
        else
        {
            HorizontalHighlight.SetActive(false);
        }

        if ((!Dragging || dragDirection != Direction.Horizontal) && highlightColumn != -1 && sm.AvailableForDragging)
        {
            VerticalHighlight.SetActive(true);
        }
        else
        {
            VerticalHighlight.SetActive(false);
        }
    }
}
