﻿using System;
using System.Collections;
using System.IO;
using Toast.SmartDownloader;
using UnityEngine;
using UnityEngine.UI;
using Debug = UnityEngine.Debug;

public partial class SmartDlExample : MonoBehaviour
{
	[Header("Input Fields")]
	public InputField AppkeyInputField;
	public InputField ServiceNameField;
	public InputField DstPathField;

	[Space]

	[Header("Config Sliders")]
	public Slider RetryCountSlider;
	public Slider ConnectTimeoutSlider;
	public Slider ReadTimeoutSlider;

	[Space]

	[Header("Etc.")]
	public Button ExtraButton;
	public Text ResultText;
	public ProgressBar PercentageBar;
	public RectTransform ExitPanel;

	private Coroutine _progressCoroutine;
	private ResultCode _recentResultCode = ResultCode.Unknown;

	#region Define partial methods
	partial void OnBeforeAwake();
	partial void OnCompleteDownload(DownloadResult result, DownloadProfiler profiler);
	#endregion

	void Awake()
	{
		OnBeforeAwake();

		AppkeyInputField.text = SmartDlExampleConfiguration.AppKey;
		ServiceNameField.text = SmartDlExampleConfiguration.ServiceName;
		DstPathField.text = SmartDlExampleConfiguration.DownloadPath;

		RetryCountSlider.value = SmartDlExampleConfiguration.RetryCount;
		ConnectTimeoutSlider.value = SmartDlExampleConfiguration.ConnectionTimeoutSeconds;
		ReadTimeoutSlider.value = SmartDlExampleConfiguration.ReadTimeoutSeconds;

		AppkeyInputField.onEndEdit.AddListener(SmartDlExampleConfiguration.SaveAppKey);
		ServiceNameField.onEndEdit.AddListener(SmartDlExampleConfiguration.SaveServiceName);
		DstPathField.onEndEdit.AddListener(SmartDlExampleConfiguration.SaveDownloadPath);

		RetryCountSlider.onValueChanged.AddListener(retryCount => SmartDlExampleConfiguration.SaveRetryCount((int)retryCount));
		ConnectTimeoutSlider.onValueChanged.AddListener(connectionTimeoutSeconds => SmartDlExampleConfiguration.SaveConnectionTimeoutSeconds((int)connectionTimeoutSeconds));
		ReadTimeoutSlider.onValueChanged.AddListener(readTimeoutSeconds => SmartDlExampleConfiguration.SaveReadTimeoutSeconds((int)readTimeoutSeconds));
	}

	void Start()
	{
		SmartDlLogger.CurrentLevel = SmartDlLogger.LogLevel.Trace;
		SmartDlLogger.OnLog += (type, log) =>
		{
			switch (type)
			{
				case SmartDlLogger.LogLevel.Trace:
				case SmartDlLogger.LogLevel.Developer:
				case SmartDlLogger.LogLevel.Debug:
				case SmartDlLogger.LogLevel.Info:
					Debug.Log(log);
					break;
				case SmartDlLogger.LogLevel.Warn:
					Debug.LogWarning(log);
					break;
				case SmartDlLogger.LogLevel.Error:
					Debug.LogError(log);
					break;
				default:
					Debug.Log(log);
					break;
			}
		};
	}

	public void OnClickStartDownload()
	{
		if (string.IsNullOrEmpty(AppkeyInputField.text))
		{
			PrintResult("You MUST input appkey field");
			return;
		}

		if (string.IsNullOrEmpty(ServiceNameField.text))
		{
			PrintResult("You MUST input service name");
			return;
		}

		PrintResult("Start download");
		StopUpdateProgressCoroutine();

		#region Set DownloadConfig
		var downloadConfig = DownloadConfig.Default;
		downloadConfig.RetryDownloadCountPerFile = (int)RetryCountSlider.value;
		downloadConfig.DownloadConnectTimeout = TimeSpan.FromSeconds(ConnectTimeoutSlider.value);
		downloadConfig.DownloadReadTimeout = TimeSpan.FromSeconds(ReadTimeoutSlider.value);
		#endregion

		var profiler = new DownloadProfiler();
		profiler.Start();

		_recentResultCode = ResultCode.Unknown;
		SmartDl.SetUserId("SmartDlExample");
		SmartDl.StartDownload(SmartDlExampleConfiguration.AppKey,
			SmartDlExampleConfiguration.ServiceName,
			SmartDlExampleConfiguration.DownloadPath,
			downloadConfig,
			result =>
		{
			profiler.End();
			_recentResultCode = result.Code;

			OnCompleteDownload(result, profiler);
			if (result.IsSuccessful)
			{
				PrintResult(string.Format("Success elapsed time : {0:F2} ms / {1:F2} s",
					profiler.ElapsedMilliseconds,
					profiler.ElapsedSeconds));
			}
			else
			{
				PrintResult(string.Format("Fail to download [{0}]", result));
				StopUpdateProgressCoroutine();
			}
		});
		_progressCoroutine = StartCoroutine(UpdateProgress());
	}

	public void OnClickStopDownload()
	{
		PrintResult("Stop download");
		StopUpdateProgressCoroutine();
		SmartDl.StopDownload();
	}

	public void OnClickDeleteFiles()
	{
		PrintResult(FileUtil.DeleteFilesInDownloadPath() ? "Success to delete directory" : "Fail to delete directory");
	}

	void StopUpdateProgressCoroutine()
	{
		if (_progressCoroutine != null)
			StopCoroutine(_progressCoroutine);
	}

	IEnumerator UpdateProgress()
	{
		while (true)
		{
			var progress = SmartDl.Progress;

			PercentageBar.Percentage = progress.Percentage;
			PercentageBar.CompletedFileCount = progress.CompletedFileCount;
			PercentageBar.TotalFileCount = progress.TotalFileNumber;
			PercentageBar.CompletedFileBytes = progress.TotalReceivedBytes;
			PercentageBar.TotalFileBytes = progress.TotalFileBytes;

			var threadCount = progress.FileMap.Count;
			ThreadProgressContainer.Instance.ThreadCount = threadCount;
			for (int i = 0; i < threadCount; i++)
			{
				var file = progress.FileMap[i];
				ThreadProgressContainer.Instance[i].ThreadNumber = i.ToString();
				ThreadProgressContainer.Instance[i].FileName = file.FileName;
				ThreadProgressContainer.Instance[i].ProgressBar.Percentage = (file.DownloadedBytes / (float)file.TotalBytes) * 100.0f;
			}

			if (progress.IsCompleted)
				yield break;

			yield return null;
		}
	}

	private void Update()
	{
#if !UNITY_EDITOR && UNITY_ANDROID
		if (Application.platform == RuntimePlatform.Android)
		{
			if (Input.GetKey(KeyCode.Escape))
			{
		        Application.Quit();
			}
		}
#endif      
	}
}
