using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace RyWeb
{
    /// <summary>
    /// WebDav接口
    /// </summary>
    public class WebDav
    {
        private string _UserName = "";
        private string _Password = "";
        private string _WebDavUrl = "";
        /// <summary>
        /// WebDav初始化
        /// </summary>
        /// <param name="_WebDavUrl"></param>
        /// <param name="_UserName"></param>
        /// <param name="_Password"></param>
        public WebDav(string _WebDavUrl, string _UserName, string _Password)
        {
            this._UserName = _UserName;
            this._Password = _Password;
            this._WebDavUrl = _WebDavUrl;
        }
        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="_WebFilePath">相对路径,不包括域名</param>
        /// <returns></returns>
        public int DelFile(string _WebFilePath)
        {
            try
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(new Uri(_WebDavUrl + "/" + _WebFilePath));
                req.Credentials = new NetworkCredential(_UserName, _Password); //验证密码
                req.PreAuthenticate = true;
                req.Method = "DELETE";
                //req.AllowWriteStreamBuffering = true;

                req.GetResponse();
                return 1;
            }
            catch { return 0; }
        }
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="_WebFilePath"></param>
        /// <param name="_SavePath"></param>
        /// <returns></returns>
        public int Download(string _WebFilePath, string _SavePath)
        {
            return Download(_WebFilePath, _SavePath,out _);
        }
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="_WebFilePath"></param>
        /// <param name="_SavePath"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public int Download(string _WebFilePath,string _SavePath,out string error)
        {
            error = "";
            try
            {
                System.Uri myURi = new System.Uri(_WebFilePath);
                WebRequest req = WebRequest.Create(myURi);
                req.Credentials = new NetworkCredential(_UserName, _Password); //验证密码
                req.Method = "GET";
                req.Timeout = System.Threading.Timeout.Infinite;
                WebResponse res = req.GetResponse();
                Stream inStream = res.GetResponseStream();

                FileStream fs = new FileStream(_SavePath, FileMode.OpenOrCreate);

                byte[] inData = new byte[4096];
                int bytesRead = inStream.Read(inData, 0, inData.Length);
                while (bytesRead > 0)
                {
                    fs.Write(inData, 0, bytesRead);
                    bytesRead = inStream.Read(inData, 0, inData.Length);
                }
                fs.Close();
                inStream.Close();
            }
            catch(Exception ex)
            {
                error = ex.Message;
                return -1;
            }
            return 1;
        }
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="_WebFilePath"></param>
        /// <param name="_LocalFile"></param>
        /// <returns></returns>
        public int Upload(string _WebFilePath, string _LocalFile)
        {
            return Upload(_WebFilePath, _LocalFile,out _);
        }
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="_WebFilePath"></param>
        /// <param name="_LocalFile"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public int Upload(string _WebFilePath, string _LocalFile,out string error)
        {
            error = "";
            try
            {
                System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)WebRequest.Create(new Uri(_WebDavUrl + "/" + _WebFilePath));  //Http和服务器交互
                req.Credentials = new NetworkCredential(_UserName, _Password); //验证密码
                req.PreAuthenticate = true;
                req.Method = "PUT";//采用PUT方式
                req.AllowWriteStreamBuffering = true;

                Stream reqStream = req.GetRequestStream();
                FileStream rdm = new FileStream(_LocalFile, FileMode.Open); //打开本地文件流

                byte[] inData = new byte[4096];
                int byteRead = rdm.Read(inData, 0, inData.Length);  //二进制读文件
                while (byteRead > 0)
                {
                    reqStream.Write(inData, 0, byteRead); //响应流写入
                    byteRead = rdm.Read(inData, 0, inData.Length);
                }
                rdm.Close();
                reqStream.Close();

                req.GetResponse(); //提交
            }
            catch (Exception e)
            {
                error=e.Message;
                return 0;
            }
            return 1; //正确返回
        }
        //----新建文件夾----
        /// <summary>
        /// 新建文件夹
        /// </summary>
        /// <param name="Path"></param>
        /// <returns></returns>
        public int CreateDir(string Path)
        {
            return CreateDir(Path, out _);
        }
        //----新建文件夾----
        /// <summary>
        /// 新建文件夹
        /// </summary>
        /// <param name="Path">文件夹路径</param>
        /// <param name="error"></param>
        /// <returns></returns>
        public int CreateDir(string Path,out string error)
        {
            error = "";
            var dir_split = Path.Split('/');
            var path = "";
            for (int i = 0; i < dir_split.Length; i++)
            {
                if (dir_split[i].Length == 0) { continue; }
                if (path.Length > 0) { path += "/"; }
                path += dir_split[i];
                _createdir(path, out var _error);
                if(_error.Length>0)
                {
                    error = _error;
                }
            }
            if (error.Length == 0)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
        //----新建文件夾----
        /// <summary>
        /// 新建文件夹
        /// </summary>
        /// <param name="Path"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        private int _createdir(string Path, out string error)
        {
            error = "";
            try
            {
                // Create the HttpWebRequest object. 
                System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)WebRequest.Create(new Uri(_WebDavUrl + "/" + Path));  //Http和服务器交互
                req.Credentials = new NetworkCredential(_UserName, _Password); //验证密码
                // Specify the method. 
                req.Method = "MKCOL";

                HttpWebResponse objResponse = (System.Net.HttpWebResponse)req.GetResponse();

                // Close the HttpWebResponse object. 
                objResponse.Close();
                return 1;
            }
            catch (Exception ex)
            {
                error = ex.Message;
                return 0;
            }
        }
        /// <summary>
        ///将文件或目录列出来
        /// </summary>
        /// <param name="Path"></param>
        /// <param name="deep"></param>
        /// <returns></returns>
        public SortedList<string, ServerFileAttributes> GetContents(string Path, bool deep)
        {
            var uri = new Uri(_WebDavUrl + "/" + Path);
            HttpWebRequest _httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
            _httpWebRequest.Headers.Add("Translate: f");
            _httpWebRequest.Credentials = new NetworkCredential(_UserName, _Password); //验证密码
            string _requestString = @"<?xml version=""1.0"" encoding=""utf-8""?>" +
                  @"<a:propfind xmlns:a=""DAV:"">" +
                  "<a:prop>" +
                  "<a:displayname/>" +
                  "<a:iscollection/>" +
                  "<a:getlastmodified/>" +
                  "</a:prop>" +
                  "</a:propfind>";

            _httpWebRequest.Method = "PROPFIND";
            if (deep == true)
                _httpWebRequest.Headers.Add("Depth: infinity");
            else
                _httpWebRequest.Headers.Add("Depth: 1");
            _httpWebRequest.ContentLength = _requestString.Length;
            _httpWebRequest.ContentType = "text/xml";

            Stream _requestStream = _httpWebRequest.GetRequestStream();
            _requestStream.Write(Encoding.UTF8.GetBytes(_requestString), 0, Encoding.ASCII.GetBytes(_requestString).Length);
            _requestStream.Close();

            HttpWebResponse _httpWebResponse;
            StreamReader _streamReader;
            try
            {
                _httpWebResponse = (HttpWebResponse)_httpWebRequest.GetResponse();
                _streamReader = new StreamReader(_httpWebResponse.GetResponseStream());
            }
            catch (WebException ex)
            {
                throw ex;
            }

            StringBuilder _stringBuilder = new StringBuilder();

            char[] _chars = new char[1024];
            int _bytesRead = 0;

            _bytesRead = _streamReader.Read(_chars, 0, 1024);

            while (_bytesRead > 0)
            {
                _stringBuilder.Append(_chars, 0, _bytesRead);
                _bytesRead = _streamReader.Read(_chars, 0, 1024);
            }
            _streamReader.Close();

            XmlDocument _xmlDocument = new XmlDocument();
            _xmlDocument.LoadXml(_stringBuilder.ToString());

            XmlNamespaceManager _xmlNamespaceManager = new XmlNamespaceManager(_xmlDocument.NameTable);
            _xmlNamespaceManager.AddNamespace("a", "DAV:");

            XmlNodeList _nameList = _xmlDocument.SelectNodes("//a:prop/a:displayname", _xmlNamespaceManager);
            XmlNodeList _isFolderList = _xmlDocument.SelectNodes("//a:prop/a:iscollection", _xmlNamespaceManager);
            XmlNodeList _lastModifyList = _xmlDocument.SelectNodes("//a:prop/a:getlastmodified", _xmlNamespaceManager);
            XmlNodeList _hrefList = _xmlDocument.SelectNodes("//a:href", _xmlNamespaceManager);

            SortedList<string, ServerFileAttributes> _sortedListResult = new SortedList<string, ServerFileAttributes>();
            ServerFileAttributes _serverFileAttributes;

            for (int i = 0; i < _nameList.Count; i++)
            {
                if (_hrefList[i].InnerText.ToLower(new CultureInfo("en-US")).TrimEnd(new char[] { '/' }) != uri.AbsoluteUri.ToLower(new CultureInfo("en-US")).TrimEnd(new char[] { '/' }))
                {
                    _serverFileAttributes = new ServerFileAttributes();
                    _serverFileAttributes.Name = _nameList[i].InnerText;
                    _serverFileAttributes.IsFolder = Convert.ToBoolean(Convert.ToInt32(_isFolderList[i].InnerText));
                    _serverFileAttributes.Url = _hrefList[i].InnerText;
                    _serverFileAttributes.LastModified = Convert.ToDateTime(_lastModifyList[i].InnerText);
                    _sortedListResult.Add(_serverFileAttributes.Url, _serverFileAttributes);
                }
            }
            return _sortedListResult;
        }
    }
    /// <summary>
    /// 定义每个文件或目录的属性
    /// </summary>
    public struct ServerFileAttributes
    {
        /// <summary>
        /// 文件名
        /// </summary>
        public string Name;
        /// <summary>
        /// 是否是文件夹
        /// </summary>
        public bool IsFolder;
        /// <summary>
        /// 网址
        /// </summary>
        public string Url;
        /// <summary>
        /// 最后修改时间
        /// </summary>
        public DateTime LastModified;
    }
}
