﻿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
{
    public InputField AppkeyInputField;
    public InputField ServiceNameField;
    public InputField DstPathField;

    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;

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

    void Start()
    {
        SmartDlLogger.CurrentLevel = SmartDlLogger.LogLevel.Developer;
        SmartDlLogger.OnLog += (type, log) =>
        {
            switch (type)
            {
                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:
                    throw new ArgumentOutOfRangeException("type", type, null);
            }
        };
    }

    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();

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

        _recentResultCode = ResultCode.Unknown;
        SmartDl.StartDownload(SmartDlExampleConfiguration.AppKey, SmartDlExampleConfiguration.ServiceName, SmartDlExampleConfiguration.DownloadPath, 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;
        }
    }    
}
