using System;
using System.IO;
using UnityEngine;
using UnityEngine.UI;

namespace Cryville.Common.Unity {
	public class FileDialog : MonoBehaviour {
		Transform panel;
		Transform title;
		Transform drives;
		Transform dirs;
		Transform files;

		public Action Callback { private get; set; }

#if UNITY_ANDROID && !UNITY_EDITOR_WIN
		string androidStorage = "";
#endif

		string fileName = "";
		public string FileName {
			get { return fileName; }
		}

		public string[] m_filter = new string[]{};
		public string[] Filter {
			set { m_filter = value; }
		}

#pragma warning disable IDE0051
		void Start() {
			panel = gameObject.transform.Find("Panel");
			title = panel.Find("Title/Text");
			drives = panel.Find("Drives/DrivesInner");
			dirs = panel.Find("Directories/DirectoriesInner");
			files = panel.Find("Files/FilesInner");
			if (CurrentDirectory == null) {
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
				CurrentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
#elif UNITY_ANDROID
				using (AndroidJavaClass ajc=new AndroidJavaClass("android.os.Environment"))
				using (AndroidJavaObject file=ajc.CallStatic<AndroidJavaObject>("getExternalStorageDirectory")) {
					androidStorage = file.Call<string>("getAbsolutePath");
					CurrentDirectory = new DirectoryInfo(androidStorage);
				}
#else
#error No default directory
#endif
			}
			UpdateGUI();
		}
#pragma warning restore IDE0051

		public void Show() {
			fileName = null;
			gameObject.SetActive(true);
		}

		public void Close() {
			if (Callback != null) Callback.Invoke();
			gameObject.SetActive(false);
		}

		public DirectoryInfo CurrentDirectory;

		void OnDriveChanged(string s) {
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
			CurrentDirectory = new DirectoryInfo(s);
#elif UNITY_ANDROID
			switch (s) {
				case "?storage":
					CurrentDirectory = new DirectoryInfo(androidStorage);
					break;
			}
#else
#error No change drive logic
#endif
			UpdateGUI();
		}

		void OnDirectoryChanged(string s) {
			CurrentDirectory = new DirectoryInfo(CurrentDirectory.FullName + "/" + s);
			UpdateGUI();
		}

		void OnFileChanged(string s) {
			fileName = s;
			Close();
		}

		void UpdateGUI() {
			title.GetComponent<Text>().text = CurrentDirectory.FullName;

			CallHelper.Purge(drives);
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
			var dl = Directory.GetLogicalDrives();
			foreach (string d in dl) {
				GameObject btn = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Common/Button"));
				btn.GetComponentInChildren<Text>().text = d;
				var ts = d;
				btn.GetComponentInChildren<Button>().onClick.AddListener(() => OnDriveChanged(ts));
				btn.transform.SetParent(drives, false);
			}
#elif UNITY_ANDROID
			GameObject sbtn = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Common/Button"));
			sbtn.GetComponentInChildren<Text>().text = "Storage";
			sbtn.GetComponentInChildren<Button>().onClick.AddListener(() => OnDriveChanged("?storage"));
			sbtn.transform.SetParent(drives, false);
#else
#error No update GUI logic
#endif

			CallHelper.Purge(dirs);
			DirectoryInfo[] subdirs = CurrentDirectory.GetDirectories();
			GameObject pbtn = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Common/Button"));
			pbtn.GetComponentInChildren<Text>().text = "..";
			pbtn.GetComponentInChildren<Button>().onClick.AddListener(() => OnDirectoryChanged(".."));
			pbtn.transform.SetParent(dirs, false);
			foreach (DirectoryInfo d in subdirs) {
				GameObject btn = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Common/Button"));
				btn.GetComponentInChildren<Text>().text = d.Name;
				var ts = d.Name;
				btn.GetComponentInChildren<Button>().onClick.AddListener(() => OnDirectoryChanged(ts));
				btn.transform.SetParent(dirs, false);
			}

			CallHelper.Purge(files);
			FileInfo[] fl = CurrentDirectory.GetFiles();
			foreach (FileInfo d in fl) {
				foreach (string ext in m_filter)
					if (d.Extension == ext) goto ext_matched;
				continue;
			ext_matched:
				GameObject btn = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Common/Button"));
				btn.GetComponentInChildren<Text>().text = d.Name + " / " + (d.Length / 1024.0).ToString("0.0 KiB");
				var ts = d.FullName;
				btn.GetComponentInChildren<Button>().onClick.AddListener(() => OnFileChanged(ts));
				btn.transform.SetParent(files, false);
			}
		}
	}
}
