using UnityEngine;
using System;
using System.Collections;


/// <summary>
///             cube = Defense);
///            pyramid = Attack);
///            sphere/torus = Movement);
/// </summary>
public class ElementalSphere : MonoBehavclops
{

	public event Action<ElementalSphere> WasPickedUp;
	public event Action<ElementalSphere> WasDropped;
	public event Action<ElementalSphere> WillEnd;


	private float _scaleFactor = 0.8f;
    public float scaleFactor
    {
        get { return _scaleFactor; }
        set
        {
            _scaleFactor = value;
            RefreshScale();
        }
    }

    //make this thing shrink instead of self, if not null
    private Transform shrinkTarget;
    public bool useWhiteBackground;
    
    public Direction direction;
    
    public GameObject cube;
    public GameObject pyramid;
    public GameObject torus;
    public Transform shapeTransform;
    private GameObject ActiveShape
    {
        get
        {
            if(Shape==ElementalAspect.Attack)
            {
                return pyramid;
            }
            if(Shape==ElementalAspect.Defense)
            {
                return cube;
            }
            else
            {
                return torus;
            }
        }
    }

    //Every callTime seconds, call the command
    public float callTime = 0.5f;
    private float curTime = 0f;
    //lose this much energy per command call
    public float energyLoss = 0.03f;
    private bool _isTriggerable;
    private bool _hasBeenDragged;
    
    private bool _isTriggering;
    public bool IsTriggerable
    {
    	get { return _isTriggerable; }
    	set 
        { 
            _isTriggerable = value; 
            Cached<Draggable>().enabled = false;
        }
    }

    private IElementalCommand command;

    private ElementalAspect _shape;
    public ElementalAspect Shape
    {
        get { return _shape; }
        set
        {
            _shape = value;
            cube.SetActive(_shape == ElementalAspect.Defense);
            pyramid.SetActive(_shape == ElementalAspect.Attack);
            torus.SetActive(_shape == ElementalAspect.Movement);
        }
    }

    private void RefreshScale()
    {
        Transform t = Cached<Transform>();
        Vector3 newScale = new Vector3(_energy * _scaleFactor, _energy * _scaleFactor, _energy * _scaleFactor);
        if(_isTriggering && shrinkTarget!=null)
        {
            shrinkTarget.localScale = newScale * t.localScale.magnitude;
        }
        else
        {
            t.localScale = newScale;
        }
    }

	private Element _element = Element.Void;
	public Element Element
	{
		get { return _element; }
		set 
		{ 
			_element = value;
			LayoutForElement();
		}
	}

	private float _energy;
	public float Energy
	{
		get { return _energy; }
		set 
		{ 
			_energy = Mathf.Clamp(value, 0f, 1f);
            RefreshScale();
            if(_energy <= 0f)
            {
            	if (WillEnd != null) WillEnd(this);
                GameObject.Destroy(gameObject);
            }
		}
	}

	public void Start()
	{
		Energy = 0.01f;
        Shape = ElementalAspect.Attack;
		Cached<Draggable>().DidStartDragging += DidStartDragging;
		Cached<Draggable>().DidStopDragging += DidStopDragging;
	}

    public void CallCommand(ShipController ship, Direction direction)
    {
        if (command == null) return;
        command.Execute(ship,direction);
        Energy -= energyLoss;
    }

	public void DidStartDragging()
	{
        _hasBeenDragged = true;
		if (WasPickedUp != null) WasPickedUp(this);
        scaleFactor = 0.75f;
	}

	private void LayoutForElement()
	{
/*        cube.renderer.material.color = Element.Color;
        pyramid.renderer.material.color = Element.Color;
        torus.renderer.material.color = Element.Color;*/
        RefreshMaterial(cube.renderer);
        RefreshMaterial(pyramid.renderer);
        RefreshMaterial(torus.renderer);
	}

    private void RefreshMaterial(Renderer renderer)
    {
        bool useMaterial = true;
        if(useMaterial && Element.Material!=null)
        {
            renderer.material = Element.Material;
        }
        else
        {
            renderer.material.color = Element.Color;
        }
    }

    public void OnMouseUp()
    {
        if (!_hasBeenDragged) {
            Shape = Shape == ElementalAspect.Defense ? ElementalAspect.Attack : Shape == ElementalAspect.Attack ? ElementalAspect.Movement : ElementalAspect.Defense;
        }
    }

    public void OnMouseDown()
    {
        if (_isTriggerable) {
            StartTriggering();
        } else if (_isTriggering) {
            _isTriggering = false;
            _isTriggerable = true;
        }
	}

    protected void StartTriggering()
    {
        _isTriggering = true;
        _isTriggerable = false;
        command = ElementalCommandFactory.Instance.CommandForElement(Element, Shape);
        if (command.clip != null)
        {
            audio.PlayOneShot(command.clip);
        }
        if(useWhiteBackground)
        {
            RefreshScale();
            shrinkTarget = ((GameObject) GameObject.Instantiate(ActiveShape, transform.position, Quaternion.identity)).transform;
            shrinkTarget.position = new Vector3(shrinkTarget.position.x,shrinkTarget.position.y,shrinkTarget.position.z-1);
            shrinkTarget.parent = shapeTransform;
            RefreshMaterial(shrinkTarget.renderer);
            ActiveShape.renderer.material.color = Color.white;
            RefreshScale();
        }
    }

	public void DidStopDragging()
	{
		if (WasDropped != null) WasDropped(this);
	}

	public void Update()
	{
        float rotX = Mathf.Sin(Time.time * 4f) * 20f;
        float rotY = Mathf.Cos(Time.time * 4f) * 20f;
        shapeTransform.localEulerAngles = new Vector3(rotX, rotY, 0f);

		if (_isTriggering) {
            curTime += Time.deltaTime;
            if(curTime>=callTime)
            {
                curTime = 0f;
                CallCommand(Game.Instance.player1, direction);
            }
		}
	}

}
