/********************************************************************
	created:	2017/11/21
	created:	21:11:2017   10:42
	filename: 	F:\work\x2m\mainline\dev\client\Assets\Script\X2Interface\IFile.cs
	file path:	F:\work\x2m\mainline\dev\client\Assets\Script\X2Interface
	file base:	IFile
	file ext:	cs
	author:		zhang qiang
	
	purpose:	file read/write operation class
*********************************************************************/
using System;
using System.IO;
using UnityEngine;
using System.Runtime.InteropServices;
//using X2Engine;

namespace Giant.Common
{
    public static class IFile
    {
#if UNITY_IPHONE || UNITY_IOS
// 		[DllImport("__Internal")]
// 		private static extern float ios_get_battery_level();

#endif
        public static string AppBundleID = "com.ztgame.xxm";
#if UNITY_ANDROID  && !UNITY_EDITOR
        static AndroidJavaClass jc_UnityPlayer;        
        static AndroidJavaObject jo_batteryIntent;      
        // CS0169
        //static IntPtr raw_fileUtility;
        static IntPtr jni_read_file_bytes;
        static IntPtr jni_extractAllAssets;
        static AndroidJavaObject jo_currentActivity;
        static AndroidJavaObject jni_currentActivity
        {
            get
            {
                if (jc_UnityPlayer == null)
                    jc_UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
                if (jo_currentActivity == null)
                    jo_currentActivity = jc_UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
                return jo_currentActivity;
            }
        }

        static AndroidJavaObject _jo_fileutility;
        public static AndroidJavaObject jni_fileutility
        {
            get
            {
                if (_jo_fileutility == null)
                {
                    LogHelper.Log("create java object FileUtility start");
                    _jo_fileutility = new AndroidJavaObject(AppBundleID + ".FileUtility");
                    LogHelper.Log("create java object FileUtility end");
                    var classid = AndroidJNI.FindClass((AppBundleID + "/FileUtility").Replace('.', '/'));
                    jni_read_file_bytes = AndroidJNI.GetMethodID(classid, "readFileBytes", "(Ljava/lang/String;)[B");
                    jni_extractAllAssets = AndroidJNI.GetMethodID(classid, "extractAllAssets", "(Ljava/lang/String;)V");
                    //LogHelper.Log("jni_read_file_bytes", jni_read_file_bytes, "extractAllAssets", jni_extractAllAssets);
                    //jni_is_file_exist = AndroidJNI.GetMethodID(classid, "isFileExist", "(Ljava/lang/String;)Z");
                }
                return _jo_fileutility;
            }
        }


        static AndroidJavaObject jo_intentFilter;
        static AndroidJavaObject jni_batteryIntent
		{
			get
			{
				if (jo_intentFilter==null)
				{
					jo_intentFilter = new AndroidJavaObject("android.content.IntentFilter", new object[] { "android.intent.action.BATTERY_CHANGED" });
					
				}
				jo_batteryIntent = jni_currentActivity.Call<AndroidJavaObject>("registerReceiver", new object[] { null, jo_intentFilter });
				return jo_batteryIntent;
			}
		}
#endif

        /// Is the file exist
        /// <param name="path"> The file path</param>
        public static bool IsFileExist(string path)
        {
#if UNITY_ANDROID && !UNITY_EDITOR
            if (path.Contains("jar:file"))
            {
                if (path.Length > Application.streamingAssetsPath.Length && Application.streamingAssetsPath == path.Substring(0, Application.streamingAssetsPath.Length))
                {
                    string packpath = path.Substring(Application.streamingAssetsPath.Length, path.Length - Application.streamingAssetsPath.Length);
            
            bool ie = jni_fileutility.Call<bool>("isFileExist", packpath);
            Debug.Log(packpath + " " + ie);
                    return ie;
                }
            }

            if (File.Exists(path))
                return true;
            return false;
#else
            return File.Exists(path);
#endif

        }

        /// read file from apk files or window file
        /// <param name="path"> The file path</param>
         public static byte[] ReadApkResourceFiles(string path, bool outputLog = false)
        {
#if UNITY_ANDROID && !UNITY_EDITOR
            if (path.Contains("jar:file"))
            {
                if (path.Length > Application.streamingAssetsPath.Length && Application.streamingAssetsPath == path.Substring(0, Application.streamingAssetsPath.Length))
                {
                    string packpath = path.Substring(Application.streamingAssetsPath.Length, path.Length - Application.streamingAssetsPath.Length);

                    jvalue[] jv = new jvalue[1];
                    var utf8 = AndroidJNI.NewStringUTF(packpath);
                    jv[0].l = utf8;
                    var rt = AndroidJNI.CallObjectMethod(jni_fileutility.GetRawObject(), jni_read_file_bytes, jv);
                    AndroidJNI.DeleteLocalRef(utf8);
                    if (rt == IntPtr.Zero)
                    {
                        return null;
                    }
                    var bytes = AndroidJNI.FromByteArray(rt);
                    AndroidJNI.DeleteLocalRef(rt);
                    return bytes;
                }
            }
#endif
			try
			{
                if (File.Exists(path))
                {
                    return File.ReadAllBytes(path);
                }
                else if(outputLog)
                {
                   // LogHelper.LogWarning(LogCategory.Framework, "Can't load file: " + path.ToString());
                }
            }
            catch
            {
               // LogHelper.LogWarning(LogCategory.Framework, "Exception catched by loading file: " + path.ToString());
            }
            return null;

		


        }

        static public void ExtractAssetBundlesFromApk() {
#if UNITY_ANDROID && !UNITY_EDITOR
            jni_fileutility.Call("extractAssetBundles", Application.persistentDataPath);
#endif
        }


        static public void ExtractAssetsFromApk()
        {
#if UNITY_ANDROID     && !UNITY_EDITOR        
            jni_fileutility.Call("extractAllAssets", Application.persistentDataPath);
#endif
        }

        static public void GetExtractAssetState(
            out  int curstep,
            out int totalstep,
            out int curstepWriteBytes,
            out int curstepTotalBytes,
            out int state
            )
        {

#if UNITY_ANDROID && !UNITY_EDITOR
            curstep = jni_fileutility.Call<int>("getCurExtractStep");
            totalstep = jni_fileutility.Call<int>("getTotalExtractStep");
            curstepWriteBytes = jni_fileutility.Call<int>("getCurExtractStepWritedBytes");
            curstepTotalBytes = jni_fileutility.Call<int>("getCurExtractStepTotalBytes");
            state = jni_fileutility.Call<int>("getExtractState");
#else

            curstep = 0;
            totalstep = 1;
            curstepWriteBytes = 0;
            curstepTotalBytes = 1;
            state = 0;
#endif
        }

    

        /// delete windows file
        /// <param name="path"> The path of file </param>
        public static bool DeleteFile(string path)
        {
            try
            {
                File.Delete(path);
                return true;
            }
            catch
            {
                return false;
            }

        }

        /// delete windows dir
        /// <param name="path"> The path of dir </param>
        public static bool DeleteDirectory(string path)
        {
            try
            {
                if (!Directory.Exists(path))
                    return true;

                Directory.Delete(path, true);
                return true;
            }
            catch (Exception e)
            {
                LogHelper.LogError("delete dir error:", e.ToString());
                return false;
            }

        }

        public static bool Delete(string path)
        {
            try
            {
                if (File.Exists(path))
                    File.Delete(path);
                else if (Directory.Exists(path))
                    Directory.Delete(path, true);

                return true;
            }
            catch (Exception e)
            {
                LogHelper.LogError("delete dir error:", e.ToString());
                return false;
            }
        }

#if UNITY_EDITOR
        /// <summary>
        /// Create a new script object asset or open an exist script object asset: 
        /// Attention: Only use in editor mode
        /// </summary>
        /// <typeparam name="T">the type of scriptobject</typeparam>
        /// <param name="filePath">like,"Assets/xxx/xxx.asset"</param>
        /// <returns></returns>
        public static T OpenScriptObjectAsset<T>(string filePath) where T : ScriptableObject
        {
            int index = filePath.LastIndexOf("/");
            if(index >= 0)
            {
                string directoryPath = filePath.Substring(0, index);
                if(!System.IO.Directory.Exists(directoryPath))
                {
                    System.IO.Directory.CreateDirectory(directoryPath);
                }
            }

            T dataScriptable;
            string tmpFullPath = Application.dataPath.Replace("Assets", "");
            tmpFullPath = tmpFullPath + filePath;
            if(!System.IO.File.Exists(tmpFullPath))
            {
                /// create asset
                dataScriptable = UnityEngine.ScriptableObject.CreateInstance<T>();
                UnityEditor.AssetDatabase.CreateAsset(dataScriptable, filePath);
               // P4V.AutoAdd(filePath);
            }
            else
            {
               // P4V.AutoCheckOut(filePath);
            }
            /// load asset for edit
            dataScriptable = UnityEditor.AssetDatabase.LoadAssetAtPath<T>(filePath);
            UnityEditor.EditorUtility.SetDirty(dataScriptable);

            return dataScriptable;

        }
#endif

        /// write windows file
        /// <param name="fname"> The name of file </param>
        /// <param name="buf"> The content of file </param>
        public static bool WriteBytes(string path, byte[] buf)
        {
            string dir = Path.GetDirectoryName(path);
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            File.WriteAllBytes(path, buf);
            return true;
        }
    }
}

