using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Web.Mvc;
using Qusion.Cms.Classifications.Core;
using Qusion.Cms.Media;
using Qusion.Cms.Media.Core;
using Qusion.Cms.Media.Extensions;
using Qusion.Cms.Media.Video;
using Qusion.Cms.Users.Core;
using Qusion.Framework.Extensions;
using Qusion.Framework.IO;
using Qusion.WebApp.Areas.Qusion.Models.Validation;
using Qusion.WebApp.Areas.Qusion.Models.Videos;

namespace Qusion.WebApp.Areas.Qusion.Controllers
{
    public class VideoController : Controller
    {
        private readonly LibraryService _libraryService;
        private readonly UserService _userService;
        private readonly LabelService _labelService;
        private readonly VideoService _videoService;

        public VideoController(VideoService videoService, LibraryService libraryService, UserService userService, LabelService labelService)
        {
            _videoService = videoService;
            _libraryService = libraryService;
            _userService = userService;
            _labelService = labelService;
        }

        public FileResult Stream(Guid id)
        {
            VideoItem document = _videoService.GetById(id);
            string dir = MediaService.GetCollectionPath(document.Library);
            string path = Path.Combine(dir, document.FilePath);

            Response.Headers.Add("Content-Type", "video/mp4");
            return File(path, MimeType.GetMimeType(document.Extension), document.FileName);
        }

        /// <summary>
        /// Upload image in library.
        /// </summary>
        /// <param name="model">Model with properties.</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Upload(VideoUploadModel model)
        {
            var errors = new List<ErrorModel>();
            if (model.File.ContentLength > _videoService.Settings.MaxAllowedSize)
                errors.Add(new ErrorModel {Key = "MaxSize", Value = "This file is larger then is allowed!"});

            string[] allowedExtensions = _videoService.Settings.AllowedExtensions.Split(',');

            bool isImage = false;
            foreach (string allowedExtension in allowedExtensions)
            {
                if (model.File.FileName.ToLower().EndsWith(allowedExtension))
                    isImage = true;
            }

            if (isImage == false)
            {
                errors.Add(new ErrorModel {Key = "Video", Value = "This is not image!"});
            }

            if (errors.Count == 0)
            {
                if (model.File != null)
                {
                    Library library = _libraryService.GetById(model.LibraryID);

                    int count = 1;
                    string fileToUpload = Path.Combine(library.Directory(), model.File.FileName);
                    string fileName = Path.GetFileNameWithoutExtension(fileToUpload);
                    string extension = Path.GetExtension(fileToUpload);

                    while (System.IO.File.Exists(fileToUpload))
                    {
                        string tempFileName = string.Format("{0}({1})", fileName, count++);
                        fileToUpload = Path.Combine(library.Directory(), tempFileName + extension);
                    }


                    model.File.SaveAs(fileToUpload);

                    if (extension == ".zip")
                    {
                        IList<string> fileExtended = ArchiveHelper.Extract(fileToUpload, library.Directory(), null,
                                                                            true);
                        foreach (string file in fileExtended)
                        {
                            var video = new VideoItem
                                            {
                                                FileName = Path.GetFileName(file),
                                                Title = Path.GetFileName(file).TitleFromFileName(),
                                                Extension = Path.GetExtension(file),
                                                CreatedBy = User.Identity.Name,
                                                Library = library,
                                            };
                            _videoService.Save(video);
                        }
                    }
                    else
                    {
                        var video = new VideoItem
                                        {
                                            FileName = model.File.FileName,
                                            Title = model.File.FileName.TitleFromFileName(),
                                            Extension = Path.GetExtension(model.File.FileName),
                                            CreatedBy = User.Identity.Name,
                                            Library = library,
                                        };
                        _videoService.Save(video);
                    }
                }
                return Json(1);
            }
            Response.StatusCode = (int) HttpStatusCode.UnsupportedMediaType.GetTypeCode();
            return Json(errors);
        }


        /// <summary>
        /// Replace video file and change title
        /// </summary>
        /// <param name="model">Model with properties.</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Edit(VideoEditInput model)
        {
            var errors = new List<ErrorModel>();
            if (model.File != null && model.File.ContentLength > _videoService.Settings.MaxAllowedSize)
                ModelState.AddModelError("MaxSize", "The video must be less than 3MB");

            string[] allowedExtensions = _videoService.Settings.AllowedExtensions.Split(',');

            if (errors.Count == 0)
            {
                VideoItem video = _videoService.GetById(model.ID);
                video.Title = model.Title;

                if (model.Labels != null)
                {
                    video.Labels.Clear();
                    foreach (string labelId in model.Labels)
                    {
                        video.Labels.Add(_labelService.GetById(new Guid(labelId)));
                    }
                }

                if (model.File != null)
                {
                    bool isVideo = false;
                    foreach (string allowedExtension in allowedExtensions)
                    {
                        if (model.File.FileName.ToLower().EndsWith(allowedExtension))
                            isVideo = true;
                    }

                    if (isVideo == false)
                    {
                        errors.Add(new ErrorModel { Key = "NoVideo", Value = "This is not video!" });
                        Response.StatusCode = (int)HttpStatusCode.UnsupportedMediaType.GetTypeCode();
                        return Json(errors);
                    }


                    _videoService.DeleteFile(video);
                    int count = 1;
                    string fileToUpload = Path.Combine(video.Library.Directory(), model.File.FileName);
                    string fileName = Path.GetFileNameWithoutExtension(fileToUpload);
                    string extension = Path.GetExtension(fileToUpload);

                    while (System.IO.File.Exists(fileToUpload))
                    {
                        string tempFileName = string.Format("{0}({1})", fileName, count++);
                        fileToUpload = Path.Combine(video.Library.Directory(), tempFileName + extension);
                    }

                    model.File.SaveAs(fileToUpload);
                    
                    video.FileName = model.File.FileName;
                    video.Title = model.Title;
                    video.Extension = Path.GetExtension(model.File.FileName);
                }
                _videoService.Save(video);
                return Json(1);
            }
            Response.StatusCode = (int)HttpStatusCode.UnsupportedMediaType.GetTypeCode();
            return Json(errors);
        }
    }
}