using System;
using UnityEditor.SceneManagement;
using UnityEngine;

namespace UnityEditor.Rendering.Converter
{
    [Serializable]
    internal class RenderPipelineConverterAssetItem : IRenderPipelineConverterItem
    {
        public string assetPath { get; }
        public string guid { get; }

        public string name => assetPath;

        public string info => guid;

        public bool isEnabled { get; set; }
        public string isDisabledMessage { get; set; }

        public RenderPipelineConverterAssetItem(string id)
        {
            if (!GlobalObjectId.TryParse(id, out var gid))
                throw new ArgumentException(nameof(id), $"Unable to perform GlobalObjectId.TryParse with the given id {id}");

            assetPath = AssetDatabase.GUIDToAssetPath(gid.assetGUID);
            guid = gid.ToString();
        }

        public RenderPipelineConverterAssetItem(GlobalObjectId gid, string assetPath)
        {
            if (!AssetDatabase.AssetPathExists(assetPath))
                throw new ArgumentException(nameof(assetPath), $"{assetPath} does not exist");

            this.assetPath = assetPath;
            guid = gid.ToString();
        }

        public UnityEngine.Object LoadObject()
        {
            UnityEngine.Object obj = null;

            if (GlobalObjectId.TryParse(guid, out var globalId))
            {
                // Try loading the object
                // TODO: Upcoming changes to GlobalObjectIdentifierToObjectSlow will allow it
                //       to return direct references to prefabs and their children.
                //       Once that change happens there are several items which should be adjusted.
                obj = GlobalObjectId.GlobalObjectIdentifierToObjectSlow(globalId);

                // If the object was not loaded, it is probably part of an unopened scene or prefab;
                // if so, then the solution is to first load the scene here.
                var objIsInSceneOrPrefab = globalId.identifierType == 2; // 2 is IdentifierType.kSceneObject
                if (!obj &&
                    objIsInSceneOrPrefab)
                {
                    // Open the Containing Scene Asset or Prefab in the Hierarchy so the Object can be manipulated
                    var mainAssetPath = AssetDatabase.GUIDToAssetPath(globalId.assetGUID);
                    var mainAsset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(mainAssetPath);
                    AssetDatabase.OpenAsset(mainAsset);

                    // If a prefab stage was opened, then mainAsset is the root of the
                    // prefab that contains the target object, so reference that for now,
                    // until GlobalObjectIdentifierToObjectSlow is updated
                    if (PrefabStageUtility.GetCurrentPrefabStage() != null)
                    {
                        obj = mainAsset;
                    }

                    // Reload object if it is still null (because it's in a previously unopened scene)
                    if (!obj)
                    {
                        obj = GlobalObjectId.GlobalObjectIdentifierToObjectSlow(globalId);
                    }
                }
            }

            return obj;
        }

        public void OnClicked()
        {
            EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(assetPath));
        }
    }
}