using System;
using System.Collections.Generic;
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 event Action OnClose;

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

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

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

		public Dictionary<string, string> m_presetPaths = new Dictionary<string, string>();
		public Dictionary<string, string> PresetPaths {
			get { return m_presetPaths; }
			set { m_presetPaths = value; }
		}

		GameObject prefabButton;

		void Start() {
			prefabButton = Resources.Load<GameObject>("Common/Button");
			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(0);
		}

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

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

		public DirectoryInfo CurrentDirectory;

		void ChangeDirectory(DirectoryInfo s) {
			CurrentDirectory = s;
			UpdateGUI(1);
		}

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

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

			if (depth <= 0) {
				CallHelper.Purge(drives);
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
				var dl = Directory.GetLogicalDrives();
				foreach (string d in dl) {
					GameObject btn = Instantiate(prefabButton);
					btn.GetComponentInChildren<Text>().text = d;
					btn.GetComponentInChildren<Button>().onClick.AddListener(() => ChangeDirectory(new DirectoryInfo(d)));
					btn.transform.SetParent(drives, false);
				}
#elif UNITY_ANDROID
				GameObject sbtn = GameObject.Instantiate<GameObject>(prefabButton);
				sbtn.GetComponentInChildren<Text>().text = "Storage";
				sbtn.GetComponentInChildren<Button>().onClick.AddListener(() => OnDriveChanged(new DirectoryInfo(androidStorage)));
				sbtn.transform.SetParent(drives, false);
#else
#error No update GUI logic
#endif
				foreach (var p in m_presetPaths) {
					var d = new DirectoryInfo(p.Value);
					if (d.Exists) {
						GameObject btn = Instantiate(prefabButton);
						btn.GetComponentInChildren<Text>().text = p.Key;
						btn.GetComponentInChildren<Button>().onClick.AddListener(() => ChangeDirectory(d));
						btn.transform.SetParent(drives, false);
					}
				}
			}

			CallHelper.Purge(dirs);
			DirectoryInfo[] subdirs = CurrentDirectory.GetDirectories();
			GameObject pbtn = Instantiate(prefabButton);
			pbtn.GetComponentInChildren<Text>().text = "..";
			pbtn.GetComponentInChildren<Button>().onClick.AddListener(() => ChangeDirectory(new DirectoryInfo(Path.Combine(CurrentDirectory.FullName, ".."))));
			pbtn.transform.SetParent(dirs, false);
			foreach (DirectoryInfo d in subdirs) {
				GameObject btn = Instantiate(prefabButton);
				btn.GetComponentInChildren<Text>().text = d.Name;
				var ts = d;
				btn.GetComponentInChildren<Button>().onClick.AddListener(() => ChangeDirectory(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) {
						GameObject btn = Instantiate(prefabButton);
						btn.GetComponentInChildren<Text>().text = d.Name + " / " + (d.Length / 1024.0).ToString("0.0 KiB");
						var ts = d.FullName;
						btn.GetComponentInChildren<Button>().onClick.AddListener(() => SelectFile(ts));
						btn.transform.SetParent(files, false);
						break;
					}
				}
			}
		}
	}
}
