using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

abstract class ActionItemBase
{
    public int gameid = 0;
    public float time = 0f;//秒数
    public float step = 0;//每秒移动的长度
    public float len = 0;//总长度
    public float nowLen = 0;//当前长度
    public int aid = 0;
    public ActionBack back = null;
    protected ActionItemBase(int gameid, float time, float step, float len, int aid)
    {
        this.gameid = gameid;
        this.time = time;
        this.step = step;
        this.len = len;
        this.aid = aid;
    }

    public abstract bool update(float dt,GameObject gameObject);
    public void callback(GameObject gameObject)
    {
        if(back != null)
        {
            back(gameObject, aid);
        }
    }
    public Vector2 initStep(Vector2 vector1, Vector2 vector2,float time)
    {
        Vector2 diff = (vector1 - vector2);
        len = diff.magnitude;
        if (time.Equals(0.0f))
        {
            time = 0.000001f;
        }
        Vector2 normalized = diff.normalized;
        step = len / time;
        return normalized;
    }
}
class ActionItemMove : ActionItemBase
{
    private Vector2 srcpos;
    private Vector2 normalized;
    private bool isAbs;
    public ActionItemMove(int gameid,float time,int aid,Vector2 nowPos,  Vector2 targetPos,bool isAbsolute):base(gameid, time,0,0,aid)
    {
        srcpos = nowPos;
        normalized = initStep(targetPos, nowPos, time);
        isAbs = isAbsolute;
    }
    public override bool update(float dt, GameObject gameObject)
    {
        nowLen = nowLen + dt * step;
        Vector2 nowPos = srcpos + (normalized * nowLen);
        if(isAbs)
        {
            gameObject.transform.position = nowPos;
        }
        else
        {
            gameObject.transform.localPosition = nowPos;
        }
        if(nowLen >= len)
        {
            step = 0;
            return false;
        }
        else
        {
            return true;
        }
    }
}
class ActionItemScale :ActionItemBase
{
    private Vector2 srcScale;
    private Vector2 normalized;
    public ActionItemScale(int gameid, float time, int aid, Vector2 nowScale, Vector2 targetScale) : base(gameid, time, 0, 0, aid)
    {
        srcScale = nowScale;
        normalized = initStep(targetScale, nowScale, time);
    }
    public override bool update(float dt, GameObject gameObject)
    {
        nowLen = nowLen + dt * step;
        Vector2 nowScale = srcScale + (normalized * nowLen);
        gameObject.transform.localScale = nowScale;
        if (nowLen >= len)
        {
            step = 0;
            return false;
        }
        else
        {
            return true;
        }
    }
}
public class ActionManages
{
    private static ActionManages instance = new ActionManages();
    private static Dictionary<int, GameObject> objects = new Dictionary<int, GameObject>();
    private static List<ActionItemBase> actions = new List<ActionItemBase>();
    private static Vector3 vector3 = Vector3.zero;
    private static Quaternion quaternion = Quaternion.identity;
    private ActionManages()
    {
    }
    public static ActionManages getInstance()
    {
        return instance;
    }
    public static void update()
    {
        float dt = Time.deltaTime;
        //暂时回调后直接消除，以后扩展循环
        List<int> backs = new List<int>();
        List<int> removeList = new List<int>();
        for (int j = 0; j < actions.Count; j++)
        {
            var item = actions[j];
            if(item.update(dt, objects[item.gameid]) == false)
            {
                backs.Add(j);
            }
        }
        if(backs.Count > 0 )
        {
            for (int j = 0; j < backs.Count; j++)
            {
                actions[j].callback(objects[actions[j].gameid]);
                removeList.Add(actions[j].aid);
            }
        }
        if(removeList.Count > 0)
        {
            for (int i = 0; i < removeList.Count; i++)
            {
                var aid = removeList[i];
                for (int j = 0; j < actions.Count; j++)
                {
                    if (actions[j].aid == aid)
                    {
                        actions.RemoveAt(j);
                        break;
                    }
                }
            }
        }
    }
    private static int getAid()
    {
        System.Random random = new System.Random();
        while (true) {
            int rand = random.Next(500, int.MaxValue - 50);
            for (int i = 0; i < actions.Count; i++)
            {
                if (actions[i].aid.Equals(rand))
                {
                    rand = 0;
                    break;
                }
            }if(rand > 0) {
                return rand;
            }
        }
    }    
    public static int addMoveByAbsolutePos(GameObject gameObject,Vector2 targetPos,float t, ActionBack actionBack = null)
    {
        int gid = gameObject.GetInstanceID();
        if(objects.ContainsKey(gid) == false)
        {
            objects.Add(gid, gameObject);
        }
        gameObject.transform.GetPositionAndRotation(out vector3,out quaternion);
        int aid = getAid();
        ActionItemBase actionItemBase = new ActionItemMove(gid,t,aid,new Vector2(vector3.x,vector3.y),targetPos,true);
        if(actionBack != null) { 
            actionItemBase.back = actionBack;
        }
        actions.Add(actionItemBase);
        return aid;
    }

    public static int addMoveByRelativePos(GameObject gameObject, Vector2 targetPos, float t, ActionBack actionBack = null)
    {
        int gid = gameObject.GetInstanceID();
        if (objects.ContainsKey(gid) == false)
        {
            objects.Add(gid, gameObject);
        }
        gameObject.transform.GetLocalPositionAndRotation(out vector3, out quaternion);
        int aid = getAid();
        ActionItemBase actionItemBase = new ActionItemMove(gid, t, aid, new Vector2(vector3.x, vector3.y), targetPos, false);
        if (actionBack != null)
        {
            actionItemBase.back = actionBack;
        }
        actions.Add(actionItemBase);
        return aid;
    }
    public static int addMoveByScale(GameObject gameObject, Vector2 targetScale, float t, ActionBack actionBack = null)
    {
        int gid = gameObject.GetInstanceID();
        if (objects.ContainsKey(gid) == false)
        {
            objects.Add(gid, gameObject);
        }
        vector3 = gameObject.transform.localScale;
        int aid = getAid();
        ActionItemBase actionItemBase = new ActionItemScale(gid, t, aid, new Vector2(vector3.x, vector3.y), targetScale);
        if (actionBack != null)
        {
            actionItemBase.back = actionBack;
        }
        actions.Add(actionItemBase);
        return aid;
    }
    public static void clearAllAction()
    {
        objects.Clear();
        actions.Clear();
    }
}
