using UnityEngine;
using UnityEditor;
using System.IO;
using System;
using UnityEngine.Video;

public class COCOARBuilder : Editor
{
    public static string AssetBundlesOutputPath_iOS = Application.dataPath + "/Assetbundle/iOS";
    public static string AssetBundlesOutputPath_android = Application.dataPath + "/Assetbundle/android";
    private static BuildAssetBundleOptions androidOptions = BuildAssetBundleOptions.None;

    private static ModelEntity entity;
    private static string unityVersion = "2019.4";

    #region Tag
    private static string strTag1 = "『2019.4』バージョンで作成してください。";
    private static string strTag2 = "ビルド対象のオブジェクト名：";
    private static string strTag3 = "ビルド中...";
    private static string strTag4 = "ビルドが失敗しました";
    private static string strTag5 = "ビルドが成功しました";
    private static string strTag6 = "ビルド対象のオブジェクトを選択してください。";
    private static string strTag7 = "削除";
    private static string strTag8 = "Instantiate機能を利用するにはパーティクルファイルの登録が必要です。";
    private static string strTag9 = "Material、Plane Appear Objectを少なくとも一つ設定してください。";
    private static string strTag10 = "Target Planeを設定してください。";
    #endregion

    [MenuItem("COCOAR/Build Selected")]
    static void CreateAssetBunldesFromSelection()
    {
        Caching.ClearCache();
        ClearAssetBundlesName();

        entity = new ModelEntity();
        entity.version_info = Application.unityVersion;
        if (!entity.version_info.Contains(unityVersion))
        {
            Debug.LogError(strTag1);
            return;
        }

        string path = AssetDatabase.GetAssetPath(Selection.activeObject);

        string selectedFilename = "";

        if (path != string.Empty)
        {
            selectedFilename = Selection.activeObject.name;
            string strInfo = string.Format("{0}{1} {2}", strTag2, selectedFilename, strTag3);
            Debug.Log(strInfo);
            try
            {
                AssetImporter assetImporter = AssetImporter.GetAtPath(path);

                assetImporter.assetBundleName = "COCOAR2_3D";

                IsContinueNativeVideo(Selection.gameObjects);

                entity.bAlwaysRecoPlane = GetIsAlwaysReco(Selection.gameObjects);

                entity.bCamDisplay = IsCamDisplay(Selection.gameObjects);

                #region Ios AssetBunle
                IosWrite();
                #endregion

                #region Android AssetBunle
                AndroidWrite();
                #endregion

                AssetDatabase.Refresh();
                DeleteFiles(AssetBundlesOutputPath_android, "android");
                DeleteFiles(AssetBundlesOutputPath_iOS, "iOS");

                Debug.Log(string.Format("{0} {1}", selectedFilename, strTag5));
            }
            catch (Exception ex)
            {
                Debug.LogError(string.Format("{0} {1}", selectedFilename, strTag4));
                Debug.LogError("Exception info ==" + ex.Message);
            }
        }
        else
        {
            Debug.LogError(strTag6);
        }
    }

    static void IosWrite()
    {
        if (!Directory.Exists(AssetBundlesOutputPath_iOS))
        {
            Directory.CreateDirectory(AssetBundlesOutputPath_iOS);
        }
        else
        {
            DeleteDir(AssetBundlesOutputPath_iOS);
        }
        BuildPipeline.BuildAssetBundles(AssetBundlesOutputPath_iOS, BuildAssetBundleOptions.None, BuildTarget.iOS);
        File.WriteAllText(AssetBundlesOutputPath_iOS + "/version", entity.version_info);//web user
        File.WriteAllText(AssetBundlesOutputPath_iOS + "/info", JsonUtility.ToJson(entity));
    }

    static void AndroidWrite()
    {
        if (!Directory.Exists(AssetBundlesOutputPath_android))
        {
            Directory.CreateDirectory(AssetBundlesOutputPath_android);
        }
        else
        {
            DeleteDir(AssetBundlesOutputPath_android);
        }
        BuildPipeline.BuildAssetBundles(AssetBundlesOutputPath_android, androidOptions, BuildTarget.Android);
        File.WriteAllText(AssetBundlesOutputPath_android + "/version", entity.version_info);  //web user
        File.WriteAllText(AssetBundlesOutputPath_android + "/info", JsonUtility.ToJson(entity));
    }

    /// <summary>  
    /// ClearAssetBundles  
    /// </summary>  
    static void ClearAssetBundlesName()
    {
        int length = AssetDatabase.GetAllAssetBundleNames().Length;
        string[] oldAssetBundleNames = new string[length];
        for (int i = 0; i < length; i++)
        {
            oldAssetBundleNames[i] = AssetDatabase.GetAllAssetBundleNames()[i];
        }

        for (int j = 0; j < oldAssetBundleNames.Length; j++)
        {
            AssetDatabase.RemoveAssetBundleName(oldAssetBundleNames[j], true);
        }
        length = AssetDatabase.GetAllAssetBundleNames().Length;
    }

    /// <summary>
    /// DeleteFiles
    /// </summary>
    /// <param name="deleteFilepath">Delete filepath.</param>
    /// <param name="strWith">String with.</param>
    static void DeleteFiles(string deleteFilepath, string strWith)
    {
        DirectoryInfo folder = new DirectoryInfo(deleteFilepath);
        FileSystemInfo[] files = folder.GetFileSystemInfos();
        int length = files.Length;
        for (int i = 0; i < length; i++)
        {
            if (files[i] is DirectoryInfo)
            {
                Debug.Log("Name==" + files[i].Name);
            }
            else
            {
                if (files[i].Name.StartsWith(strWith) || files[i].Name.EndsWith(".meta"))
                {
                    string strInfo = string.Format("{0}=={1}/{2}", strTag7, deleteFilepath, files[i].Name);
                    Debug.Log(strInfo);
                    File.Delete(deleteFilepath + "/" + files[i].Name);
                }
            }
        }
    }

    /// <summary>
    /// Delete
    /// </summary>
    /// <param name="delPath">Del path.</param>
    static void DeleteDir(string delPath)
    {
        try
        {
            DirectoryInfo strDir = new DirectoryInfo(delPath);
            FileSystemInfo[] filesInfo = strDir.GetFileSystemInfos();
            foreach (FileSystemInfo i in filesInfo)
            {
                if (i is DirectoryInfo)
                {
                    DirectoryInfo subDir = new DirectoryInfo(i.FullName);
                    subDir.Delete(true);
                }
                else
                {

                    File.Delete(i.FullName);
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    static void IsContinueNativeVideo(GameObject[] obj)
    {
        for (int i = 0; i < obj.Length; i++)
        {
            foreach (VideoPlayer item in obj[i].GetComponentsInChildren<VideoPlayer>())
            {
                if (item.source == VideoSource.VideoClip && item.clip != null)
                {
                    ChangeCompressMode();
                    return;
                }
            }
        }
    }

    static bool IsCamDisplay(GameObject[] obj)
    {
        for (int i = 0; i < obj.Length; i++)
        {
            foreach (var item in obj[i].GetComponentsInChildren<Transform>())
            {
                if (item.gameObject.layer == 8)
                {
                    return true;
                }
            }
        }
        return false;
    }

    static bool GetIsAlwaysReco(GameObject[] obj)
    {
        foreach (var item in obj)
        {
            PlaneEffectManager effectMgr = item.GetComponentInChildren<PlaneEffectManager>();
            if (effectMgr == null)
            {
                return false;
            }
            else
            {
                if (effectMgr.PlaneMaterial == null && effectMgr.PlaneAppearObject == null && (effectMgr.TargetPlane.Horizontal || effectMgr.TargetPlane.Vertical))
                {
                    Debug.LogError(strTag9);
                    throw new Exception();
                }
                else if ((effectMgr.PlaneMaterial != null || effectMgr.PlaneAppearObject != null) && (!effectMgr.TargetPlane.Horizontal && !effectMgr.TargetPlane.Vertical))
                {
                    Debug.LogError(strTag10);
                    throw new Exception();
                }
                else
                {

                    IsIncludeParticle(effectMgr.PlaneAppearObject);
                    if (!effectMgr.PlaneMaterial && !effectMgr.PlaneAppearObject && !effectMgr.TargetPlane.Horizontal && !effectMgr.TargetPlane.Vertical)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    static void IsIncludeParticle(GameObject obj)
    {
        if (obj == null) return;
        ParticleSystem[] particles = obj.GetComponentsInChildren<ParticleSystem>();
        if (particles == null || particles.Length == 0)
        {
            Debug.LogError(strTag8);
            throw new Exception();
        }
    }

    static void ChangeCompressMode()
    {
        androidOptions = BuildAssetBundleOptions.UncompressedAssetBundle;
    }
}
