using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;
using System.IO;

using EQNetwork.Objects;
using EQNetwork.Utility;
using EQNetwork.Interfaces;

namespace EQNetwork.Services
{
    public partial class EQApiService : IEQApiService
    {
        public EQTask Upload_Begin(UploadContext uploadContext, Action<Upload, EQException> onComplete)
        {
            return new EQTask((EQTask task) =>
            {
                try
                {
                    Upload upload = Upload_Begin(uploadContext);
                    onComplete(upload, null);
                }
                catch (Exception ex) { onComplete(null, new EQException(ex)); }
            });
        }
        public Upload Upload_Begin(UploadContext uploadContext)
        {
            Parameters parms = new Parameters(
                "SessionGuid", _eq.SessionGuid,
                "Name", uploadContext.Name,
                "OriginalFilepath", uploadContext.Path,
                "FileSize", uploadContext.FileSize,
                "PreferredChunkSize", uploadContext.PreferredChunkSize,
                "NumberOfChunks", uploadContext.NumberOfChunks
                );
            return new Upload(ParseXml(MakeApi2Request("Upload2_Begin", parms)));
        }

        public EQTask Upload_Complete(UploadContext uploadContext, Action<Upload, EQException> onComplete)
        {
            return new EQTask((EQTask task) =>
            {
                try
                {
                    Upload upload = Upload_Complete(uploadContext);
                    onComplete(upload, null);
                }
                catch (Exception ex) { onComplete(null, new EQException(ex)); }
            });
        }
        public Upload Upload_Complete(UploadContext uploadContext)
        {
            Parameters parms = new Parameters(
                "SessionGuid", _eq.SessionGuid,
                "UploadId", uploadContext.Upload.UploadId
                );
            return new Upload(ParseXml(MakeApi2Request("Upload2_Complete", parms)));
        }

        public EQTask Upload_ListUploads(int preferredChunkSize, int numberOfChunks, Action<List<Upload>, EQException> onComplete)
        {
            return new EQTask((EQTask task) =>
            {
                try
                {
                    List<Upload> uploads = Upload_ListUploads(preferredChunkSize, numberOfChunks);
                    onComplete(uploads, null);
                }
                catch (Exception ex) { onComplete(null, new EQException(ex)); }
            });
        }
        public List<Upload> Upload_ListUploads(int preferredChunkSize, int numberOfChunks)
        {
            Parameters parms = new Parameters(
                "SessionGuid", _eq.SessionGuid,
                "PreferredChunkSize", preferredChunkSize,
                "NumberOfChunks", numberOfChunks
                );
            return Upload.ParseList(MakeApi2Request("Upload2_ListUploads", parms));
        }

        public EQTask Upload_ListUpload(UploadContext uploadContext, Action<Upload, EQException> onComplete)
        {
            return new EQTask((EQTask task) =>
            {
                try
                {
                    Upload upload = Upload_ListUpload(uploadContext);
                    onComplete(upload, null);
                }
                catch (Exception ex) { onComplete(null, new EQException(ex)); }
            });
        }
        public Upload Upload_ListUpload(UploadContext uploadContext)
        {
            Parameters parms = new Parameters(
                "SessionGuid", _eq.SessionGuid,
                "UploadId", uploadContext.Upload.UploadId,
                "PreferredChunkSize", uploadContext.PreferredChunkSize,
                "NumberOfChunks", uploadContext.NumberOfChunks
                );
            List<Upload> uploads = Upload.ParseList(MakeApi2Request("Upload2_ListUploads", parms));
            return uploads[0];
        }

        public EQTask Upload_Chunk(UploadContext uploadContext, long chunkOffset, long chunkSize, FileUploadSpec chunk, Action<long, long, EQException> onComplete)
        {
            return new EQTask((EQTask task) =>
            {
                try
                {
                    long total;
                    long soFar = Upload_Chunk(out total, uploadContext, chunkOffset, chunkSize, chunk);
                    onComplete(soFar, total, null);
                }
                catch (Exception ex) { onComplete(0, 0, new EQException(ex)); }
            });
        }
        public long Upload_Chunk(out long total, UploadContext uploadContext, long chunkOffset, long chunkSize, FileUploadSpec chunk)
        {
            Parameters parms = new Parameters(
                "SessionGuid", _eq.SessionGuid,
                "UploadId", uploadContext.Upload.UploadId,
                "ChunkOffset", chunkOffset,
                "ChunkSize", chunkSize,
                "Chunk", chunk
                );
            XmlNode root = ParseXml(MakeApi2Request("Upload2_UploadChunk", parms));
            long uploadedSoFar = 0;
            long finalFileSize = 0;
            List<Upload> uploads = new List<Upload>();
            foreach (XmlNode node in root.ChildNodes)
            {
                if (node.Name.Equals("Uploaded", StringComparison.OrdinalIgnoreCase))
                {
                    uploadedSoFar = long.Parse(node.Attributes["SoFar"].Value);
                    finalFileSize = long.Parse(node.Attributes["Of"].Value);
                }
            }
            total = finalFileSize;
            return uploadedSoFar;
        }

        public EQTask Upload_CancelUpload(UploadContext uploadContext, Action<Upload, EQException> onComplete)
        {
            return new EQTask((EQTask task) =>
            {
                try
                {
                    Upload upload = Upload_CancelUpload(uploadContext);
                    onComplete(upload, null);
                }
                catch (Exception ex) { onComplete(null, new EQException(ex)); }
            });
        }
        public Upload Upload_CancelUpload(UploadContext uploadContext)
        {
            Parameters parms = new Parameters(
                "SessionGuid", _eq.SessionGuid,
                "UploadId", uploadContext.Upload.UploadId
                );
            return new Upload(ParseXml(MakeApi2Request("Upload2_CancelUpload", parms)));
        }

        public EQTask Upload_CreateContentFile(ContentFile contentFile, UploadContext uploadContext, Action<ContentFile, EQException> onComplete)
        {
            return new EQTask((EQTask task) =>
            {
                try
                {
                    Upload_CreateContentFile(ref contentFile, uploadContext);
                    onComplete(contentFile, null);
                }
                catch (Exception ex) { onComplete(null, new EQException(ex)); }
            });
        }
        public void Upload_CreateContentFile(ref ContentFile contentFile, UploadContext uploadContext)
        {
            Parameters parms = new Parameters(
                "SessionGuid", _eq.SessionGuid,
                "UploadId", uploadContext.Upload.UploadId
                );
            parms.AddChangedProperties(contentFile);
            int contentFileId = int.Parse(ParseXml(MakeApi2Request("Upload2_CreateContentFile", parms)).InnerText);
            contentFile = ContentFile_Get(contentFileId);
        }
    }
}
