using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
using System.Net.Http.Headers;

namespace BaroSeeSDK
{
    public class DocumentInfo
    {
        public string Name { get; set; }
        public String Url { get; set; }
        public int? Size { get; set; }
        public String Ext { get; set; }
        public String TargetFormat { get; set; }
        public bool? Lock { get; set; }

        public static string GetContentType(string ext)
        {
            if (string.IsNullOrEmpty(ext)) return null;
            ext = ("" + ext).ToLower();
            if (ext.StartsWith(".")) ext = ext.Substring(1);
            switch (ext)
            {
                case "doc": return "application/msword";
                case "docx": return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
                case "xls": return "application/vnd.ms-excel";
                case "xlsx": return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                case "ppt": return "application/vnd.ms-powerpoint";
                case "pptx": return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
                case "hwp": return "application/x-hwp";                
                case "html": return "text/html";
                case "pdf": return "application/pdf";
                default:
                    return null;
            }
        }
    }

    public interface IDocumentAPI
    {
        DocumentInfo Info(string url, ErrorHandler errorHandler = null);
        DocumentInfo Subscribe(string url, bool privateStatus = false, ErrorHandler errorHandler = null);
        bool Delete(string url, ErrorHandler errorHandler = null);
        bool SetChange(string url, ErrorHandler errorHandler = null);
        Task<Stream> GetHTML(string url, ErrorHandler errorHandler = null);
        HttpResponseMessage DownloadConvertedFile(string url, ErrorHandler errorHandler = null);
    }

    public class DocumentAPI: IDocumentAPI
    {
        private IAuthenticationProvider auth;
        public DocumentAPI(IAuthenticationProvider auth) { this.auth = auth; if (auth == null) throw new ArgumentException("Invalid authentication errorHandler"); }
        public DocumentInfo Info(string url, ErrorHandler errorHandler = null)
        {
            DocumentInfo result = null;
            ApiEntry entry = BaroSeeService.Apis[BaroSeeService.ApiEntries.document_fileinfo];
            if (auth.CurrentAccessToken == null) errorHandler.Invoke("Document.Info", System.Net.HttpStatusCode.Unauthorized, "Access token is not found");
            var data = new
            {
                Url = url
            };
            result = ApiCaller.Execute<DocumentInfo>(auth.CurrentAccessToken.Value, entry, data, new ErrorHandler[] { errorHandler });
            return result;
        }

        public DocumentInfo Subscribe(string url, bool privateStatus = false, ErrorHandler errorHandler = null)
        {
            DocumentInfo result = null;
            ApiEntry entry = BaroSeeService.Apis[BaroSeeService.ApiEntries.document_subscribe];
            if (auth.CurrentAccessToken == null) errorHandler.Invoke("Document.Subscribe", System.Net.HttpStatusCode.Unauthorized, "Access token is not found");
            var data = new
            {
                Url = url,
                Private = privateStatus
            };
            result = ApiCaller.Execute<DocumentInfo>(auth.CurrentAccessToken.Value, entry, data, new ErrorHandler[] { errorHandler });
            return result;
        }

        public bool Delete(string url, ErrorHandler errorHandler = null)
        {
            bool result = false;
            ApiEntry entry = BaroSeeService.Apis[BaroSeeService.ApiEntries.document_delete];
            if (auth.CurrentAccessToken == null) errorHandler.Invoke("Document.Delete", System.Net.HttpStatusCode.Unauthorized, "Access token is not found");
            var data = new
            {
                Url = url
            };
            result = ApiCaller.Execute<bool>(auth.CurrentAccessToken.Value, entry, data, new ErrorHandler[] { errorHandler });
            return result;
        }

        public bool SetChange(string url, ErrorHandler errorHandler = null)
        {
            bool result = false;
            ApiEntry entry = BaroSeeService.Apis[BaroSeeService.ApiEntries.document_setchange];
            if (auth.CurrentAccessToken == null) errorHandler.Invoke("Document.SetChange", System.Net.HttpStatusCode.Unauthorized, "Access token is not found");
            var data = new
            {
                Url = url
            };
            result = ApiCaller.Execute<bool>(auth.CurrentAccessToken.Value, entry, data, new ErrorHandler[] { errorHandler });
            return result;
        }

        public Task<Stream> GetHTML(string url, ErrorHandler errorHandler = null)
        {
            ApiEntry entry = BaroSeeService.Apis[BaroSeeService.ApiEntries.document_gethtml];
            if (auth.CurrentAccessToken == null) errorHandler.Invoke("Document.GetHTML", System.Net.HttpStatusCode.Unauthorized, "Access token is not found");
            ApiCaller caller = new ApiCaller(auth.CurrentAccessToken.Value);
            var data = new
            {
                Url = url
            };
            Task<HttpResponseMessage> response = caller.ExecuteAsync(entry.Method, entry.Link, data);
            try
            {                
                response.Result.EnsureSuccessStatusCode();
                if (response.Result.IsSuccessStatusCode)
                    return response.Result.Content.ReadAsStreamAsync();
                
                throw new Exception("Cannot get file data");
            }
            catch (Exception ex)
            {
                if (errorHandler != null)
                    errorHandler.Invoke("Document.GetHTML", response.Result.StatusCode, ex.Message);
            }
            return null;
        }

        public HttpResponseMessage DownloadConvertedFile(string url, ErrorHandler errorHandler = null)
        {             
            ApiEntry entry = BaroSeeService.Apis[BaroSeeService.ApiEntries.document_getconvertedfile];
            if (auth.CurrentAccessToken == null) errorHandler.Invoke("Document.DownloadConvertedFile", System.Net.HttpStatusCode.Unauthorized, "Access token is not found");
            ApiCaller caller = new ApiCaller(auth.CurrentAccessToken.Value);
            var data = new
            {
                Url = url
            };
            Task<HttpResponseMessage> response = caller.ExecuteAsync(entry.Method, entry.Link, data);
            try
            {
                response.Result.EnsureSuccessStatusCode();
                if (response.Result.IsSuccessStatusCode)                
                    return response.Result;                

                throw new Exception("Cannot get file data");
            }
            catch (Exception ex)
            {
                if (errorHandler != null)
                    errorHandler.Invoke("Document.GetHTML", response.Result.StatusCode, ex.Message);
            }
            return null;            
        }        
        
    }
}
