using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine;
using Spine.Unity;
using System.IO;

public class Move : MonoBehaviour
{
    private SkeletonAnimation hugeAnimation;
    private float currentSpeed;
    private float xSpeed;
    private float ySpeed;
    private float nextChangeTime;
    private float nextSpwanTime;
    private State currentState;
    private Side currentSide;
    private bool canTurn = false;

    public static int hugeAmount = 1;
    public static int hugeNo = 1;
    public static float previousCloneTime;
    public static string hugeSkinDirPath;
    public static string[] hugeSkinPaths;
    public static int hugeSkinNum;

    private const float moveSpeed = 0.3f;
    private const float xMinLimit = -15.0f;
    private const float xMaxLimit = 15.0f;
    private const float yMinLimit = -8.0f;
    private const float yMaxLimit = 8.0f;
    private const float edgeWidth = 0.3f;
    private const float minMoveTime = 1.0f;
    private const float maxMoveTime = 8.0f;
    private const float minStopTime = 6.0f;
    private const float maxStopTime = 13.0f;
    private const float minSpwanTime = 120.0f;
    private const float maxSpwanTime = 300.0f;
    private const float spawnRate = 0.1f;
    private const int   amountLimit = 10;

    public enum State
    {
        STOP,
        MOVE_LEFT,
        MOVE_RIGHT
    }

    public enum Side
    {
        BOTTOM,
        TOP,
        LEFT,
        RIGHT,
        CENTER
    }


    void Awake()
    {
        //INIParser ini = new INIParser();
        //ini.Open(Application.streamingAssetsPath + "/config.ini");
        //ini.Close();
        hugeSkinDirPath = Application.streamingAssetsPath + "/skin/";
        hugeSkinPaths = Directory.GetFiles(hugeSkinDirPath, "*.png");
        hugeSkinNum = hugeSkinPaths.Length;

        hugeAnimation = this.GetComponentInChildren<SkeletonAnimation>();
        xSpeed = ySpeed = 0;
        nextChangeTime = Time.time + Random.Range(minStopTime, maxStopTime);
        nextSpwanTime = Time.time + Random.Range(minSpwanTime, maxSpwanTime);
        changeState(State.STOP);
        changeSide(Side.BOTTOM);
        if (hugeNo != 1)
        {
            Invoke("changeHugeSkin", 0.5f);
        }  
    }


    public void changeState(State state)
    {
        switch (state)
        {
            case State.STOP:
                currentSpeed = 0.0f;
                hugeAnimation.AnimationName = "Wait_A02";
                break;
            case State.MOVE_LEFT:
                currentSpeed = -moveSpeed;
                hugeAnimation.AnimationName = "ActionStart_A";
                break;
            case State.MOVE_RIGHT:
                currentSpeed = moveSpeed;
                hugeAnimation.AnimationName = "ActionClose_A";
                break;
        }
        currentState = state;
        updateSpeed();
    }

    public void changeSide(Side side)
    {
        xSpeed = ySpeed = 0;
        this.GetComponent<Rigidbody2D>().gravityScale = 0;
        switch (side)
        {
            case Side.BOTTOM:
                this.GetComponent<Rigidbody2D>().gravityScale = 1;
                this.transform.rotation = Quaternion.Euler(0, 0, 0);
                break;
            case Side.TOP:
                this.transform.rotation = Quaternion.Euler(0, 0, 180);
                this.transform.position = new Vector3(this.transform.position.x, yMaxLimit, 0);
                break;
            case Side.LEFT:
                this.transform.rotation = Quaternion.Euler(0, 0, 270);
                this.transform.position = new Vector3(xMinLimit, this.transform.position.y, 0);
                break;
            case Side.RIGHT:
                this.transform.rotation = Quaternion.Euler(0, 0, 90);
                this.transform.position = new Vector3(xMaxLimit, this.transform.position.y, 0);
                break;
            case Side.CENTER:
                this.transform.rotation = Quaternion.Euler(0, 0, 0);
                break;
        }
        currentSide = side;
        updateSpeed();
    }

    public void updateSpeed()
    {
        xSpeed = ySpeed = 0;
        switch (currentSide)
        {
            case Side.BOTTOM:
                xSpeed = currentSpeed;
                break;
            case Side.TOP:
                xSpeed = currentSpeed * -1;
                break;
            case Side.LEFT:
                ySpeed = currentSpeed * -1;
                break;
            case Side.RIGHT:
                ySpeed = currentSpeed;
                break;
            case Side.CENTER:
                break;
        }
    }

    public bool checkOnWall()
    {
        if (this.transform.position.x < xMinLimit + edgeWidth && currentSide != Side.LEFT)
        {
            changeSide(Side.LEFT);
            return true;
        }
        if (this.transform.position.x > xMaxLimit - edgeWidth && currentSide != Side.RIGHT)
        {
            changeSide(Side.RIGHT);
            return true;
        }
        if (this.transform.position.y > yMaxLimit - edgeWidth && currentSide != Side.TOP)
        {
            changeSide(Side.TOP);
            return true;
        }
        return false;
    }

    public void checkTurn()
    {
        if (this.transform.position.x < xMinLimit + edgeWidth && this.transform.position.y > yMaxLimit - edgeWidth)
        {
            changeSide(currentSide == Side.LEFT ? Side.TOP : Side.LEFT);
            canTurn = false;
            return;
        }
        if (this.transform.position.x > xMaxLimit - edgeWidth && this.transform.position.y > yMaxLimit - edgeWidth)
        {
            changeSide(currentSide == Side.RIGHT ? Side.TOP : Side.RIGHT);
            canTurn = false;
            return;
        }
        if (this.transform.position.x < xMinLimit + edgeWidth && this.transform.position.y < yMinLimit + edgeWidth)
        {
            changeSide(currentSide == Side.LEFT ? Side.BOTTOM : Side.LEFT);
            canTurn = false;
            return;
        }
        if (this.transform.position.x > xMaxLimit - edgeWidth && this.transform.position.y < yMinLimit + edgeWidth)
        {
            changeSide(currentSide == Side.RIGHT ? Side.BOTTOM : Side.RIGHT);
            canTurn = false;
            return;
        }
    }

    bool checkDirection()
    {
        if (currentSide == Side.BOTTOM && this.transform.rotation.z > 0.2 || this.transform.rotation.z < -0.2)
        {
            return false;
        }
        return true;
    }

    public void spawnHuge()
    {
        hugeNo++;
        hugeAmount++;
        GameObject thisHuge = GameObject.Find(this.name);
        GameObject newHuge = Instantiate(thisHuge);
        newHuge.name = "huge" + hugeNo.ToString();
        previousCloneTime = Time.time;
        
    }

     public void changeHugeSkin()
     {
        Texture2D tex = new Texture2D(0,0);
        tex.LoadImage(File.ReadAllBytes(hugeSkinPaths[Random.Range(0, hugeSkinNum - 1)]));
        Material mat = new Material(Shader.Find("Sprites/Default"));
        mat.SetTexture("_MainTex", tex);
        GetComponentInChildren<Renderer>().material = mat;
     }


    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //changeHugeSkin();
        }

        if (Time.time >= nextChangeTime)
        {
            if (currentState == State.STOP && currentSide != Side.CENTER && checkDirection())
            {
                if (Random.Range(0.0f, 1.0f) >= 0.5f)
                {
                    changeState(State.MOVE_LEFT);
                }
                else
                {
                    changeState(State.MOVE_RIGHT);
                }
                nextChangeTime += Random.Range(minMoveTime, maxMoveTime);
                canTurn = true;
            }
            else
            {
                changeState(State.STOP);
                nextChangeTime += Random.Range(minStopTime, maxStopTime);
            }
            
        }

        if (Time.time >= nextSpwanTime)
        {
            if (Random.Range(0.0f, 1.0f) <= spawnRate && hugeAmount <= amountLimit)
            {
                spawnHuge();
            }
            nextSpwanTime += Random.Range(minSpwanTime, maxSpwanTime);
        }


        if (currentSide == Side.LEFT || currentSide == Side.RIGHT || currentSide == Side.TOP)
        {
            changeSide(currentSide);
        }

        if (canTurn)
        {
            checkTurn();
        }
        
        
        this.transform.position += new Vector3(xSpeed * Time.deltaTime, ySpeed * Time.deltaTime, 0);
    }
}
