﻿using System.Collections.Generic;
using JLGames.RocketDriver.Actions.Extensions;
using UnityEngine;
using UnityEngine.Tilemaps;

namespace JLGames.RocketDriver.Actions.Utils
{
    /// <summary>
    /// Common public behaviors under the UnityEngine.Tilemaps component
    /// UnityEngine.Tilemaps组件下的常用公共行为
    /// </summary>
    public static class TilemapUtil
    {
        //以下为设置地块行为(单独)

        /// <summary>
        /// Set tile view
        /// 设置格子显示
        /// </summary>
        /// <param name="map"></param>
        /// <param name="tile"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        public static void SetTile(this Tilemap map, TileBase tile, int x, int y, int z)
        {
            map.SetTile(new Vector3Int(x, y, z), tile);
        }

        /// <summary>
        /// Set tile view
        /// 设置格子显示
        /// </summary>
        /// <param name="map"></param>
        /// <param name="tile"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public static void SetTile(this Tilemap map, TileBase tile, int x, int y)
        {
            map.SetTile(new Vector3Int(x, y, 0), tile);
        }

        /// <summary>
        /// Set tile view
        /// 设置格子显示
        /// </summary>
        /// <param name="map"></param>
        /// <param name="tile"></param>
        /// <param name="pos"></param>
        public static void SetTile(Tilemap map, TileBase tile, Vector3Int pos)
        {
            map.SetTile(pos, tile);
        }

        //以下为设置地块行为(批量)

        /// <summary>
        /// Batch setting tile view
        /// 批量设置格子显示
        /// </summary>
        /// <param name="map"></param>
        /// <param name="tiles"></param>
        /// <param name="posArr"></param>
        public static void SetTiles(Tilemap map, TileBase[] tiles, Vector3Int[] posArr)
        {
            map.SetTiles(posArr, tiles);
        }

        /// <summary>
        /// Batch setting tile view
        /// 批量设置格子显示
        /// Set the same view in different locations
        /// 不同位置刷新相同地块
        /// </summary>
        /// <param name="map"></param>
        /// <param name="tile"></param>
        /// <param name="positions"></param>
        public static void SetTiles(this Tilemap map, TileBase tile, Vector3Int[] positions)
        {
            var tileArr = new TileBase[positions.Length];
            for (var i = tileArr.Length - 1; i >= 0; i--)
            {
                tileArr[i] = tile;
            }

            map.SetTiles(positions, tileArr);
        }

        /// <summary>
        /// Batch setting tile view
        /// 批量设置格子显示
        /// Set the same view by bound area
        /// 按区域范围刷新相同地块
        /// </summary>
        /// <param name="map"></param>
        /// <param name="tile"></param>
        /// <param name="area"></param>
        public static void SetTiles(this Tilemap map, TileBase tile, BoundsInt area)
        {
            var size = area.size;
            var tileArr = new TileBase[size.x * size.y * size.z];
            for (var i = tileArr.Length - 1; i >= 0; i--)
            {
                tileArr[i] = tile;
            }

            map.SetTilesBlock(area, tileArr);
        }

        //以下为清除地块行为--------------------

        /// <summary>
        /// Clear tile view
        /// 清除显示
        /// </summary>
        /// <param name="map"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public static void ClearTile(Tilemap map, int x, int y)
        {
            map.SetTile(new Vector3Int(x, y, 0), null);
        }

        /// <summary>
        /// Clear tile view
        /// 清除显示
        /// </summary>
        /// <param name="map"></param>
        /// <param name="pos"></param>
        public static void ClearTile(Tilemap map, Vector3Int pos)
        {
            map.SetTile(pos, null);
        }

        /// <summary>
        /// Clear tile views
        /// 批量清除显示
        /// </summary>
        /// <param name="map"></param>
        /// <param name="positions"></param>
        public static void ClearTiles(Tilemap map, Vector3Int[] positions)
        {
            var tileArr = new TileBase[positions.Length];
            map.SetTiles(positions, tileArr);
        }

        /// <summary>
        /// Clea tile view by bound area.
        /// 区域范围清除显示
        /// </summary>
        /// <param name="map"></param>
        /// <param name="area"></param>
        public static void ClearTiles(Tilemap map, BoundsInt area)
        {
            var size = area.size;
            var tileArr = new TileBase[size.x * size.y]; //元素默认值为null
            map.SetTilesBlock(area, tileArr);
        }

        /// <summary>
        /// Clea all tile views.
        /// 清除全部网格内容
        /// </summary>
        /// <param name="map"></param>
        public static void ClearTiles(Tilemap map)
        {
            map.ClearAllTiles();
        }

        //以下为统计地块行为--------------------

        private static readonly List<Vector3Int> m_TempPosList = new List<Vector3Int>();

        /// <summary>
        /// Calculate the extra Tile of newBound compared to oldBound
        /// 计算oldBound相比于newBound多出的Tile
        /// </summary>
        /// <param name="newBounds"></param>
        /// <param name="oldBounds"></param>
        /// <returns></returns>
        public static Vector3Int[] StatRemoveTiles(BoundsInt newBounds, BoundsInt oldBounds)
        {
            if (oldBounds.IsNone()) return null;
            if (newBounds.IsNone()) return oldBounds.ToArray();
            return oldBounds.Sub(newBounds);
        }

        /// <summary>
        /// Calculate the extra Tile of newBound compared to oldBound
        /// 计算newBound相比于oldBound多出的Tile
        /// </summary>
        /// <param name="newBounds"></param>
        /// <param name="oldBounds"></param>
        /// <returns></returns>
        public static Vector3Int[] StatAddTiles(BoundsInt newBounds, BoundsInt oldBounds)
        {
            if (newBounds.IsNone()) return null;
            if (oldBounds.IsNone()) return newBounds.ToArray();
            return newBounds.Sub(oldBounds);
        }
    }
}