public HttpResponseMessage UploadGalleryContentImage(HttpRequestMessage message,
            [System.Web.Http.FromUri, System.ComponentModel.DataAnnotations.Required]Nullable<int> id, [System.Web.Http.FromUri]string imageID)
        {
            if (this.HttpContext.Request.Files.Count != 1)
                return this.Request.CreateResponse(HttpStatusCode.NotAcceptable, "There are no files or more then one for uploading in the request");

            if (!id.HasValue)
                throw new Exception("Target gallery is not pointed. Query strin parameter 'id' is required");

            var gallery = GalleryRuntime.GetGallery(id.Value);
            var template = GalleryRuntime.GetTemplate(gallery.TemplateID);

            string contentpath = gallery.GetContentPath();
            string rootpath = gallery.GetDevPath();

            if (!Directory.Exists(contentpath))
                Directory.CreateDirectory(contentpath);

            var file = this.HttpContext.Request.Files[0];

            //TODO: CHANGE VALIDATE LOGIC
            if (GalleryRuntime.MaxImageSize.HasValue && GalleryRuntime.MaxImageSize.Value < file.ContentLength)
                return this.Request.CreateResponse<string>(HttpStatusCode.BadRequest, string.Format("Uploading file size is {0}byte. Max file size {1}bytes is exceeded", file.ContentLength, GalleryRuntime.MaxImageSize.Value));

            if (GalleryRuntime.MinImageSize.HasValue && file.ContentLength < GalleryRuntime.MinImageSize.Value)
                return this.Request.CreateResponse<string>(HttpStatusCode.BadRequest, string.Format("Uploading file size is {0}byte. Min file size is {1}bytes", file.ContentLength, GalleryRuntime.MaxImageSize.Value));

            string filename = file.FileName;
            string filepath = Path.Combine(contentpath, filename);

            if (File.Exists(filepath))
            {
                filepath = Common.Utils.GenerateFilePathForDuplicate(filepath);
                filename = Path.GetFileName(filepath);
            }

            //try to save original image
            try
            {
                file.SaveAs(filepath);
            }
            catch (Exception ex)
            {
                this.Logger.WriteError(ex, string.Format("Uploaded file cannot be saved to '{0}'", filepath));
                return this.Request.CreateResponse(HttpStatusCode.InternalServerError);
            }
            finally
            {
                file.InputStream.Close();
            }

            //this handler return gallery relative image url
            Common.ActionHandler<string, string> gllrUrlHandler =
                delegate(string fname)
                {
                    return string.Format("{0}/{1}", Common.Utils.GetRelativePath(GalleryRuntime.GetGalleryOutputPath(id.Value), contentpath).TrimEnd('\\').Replace('\\', '/'), fname);
                };

            lock (gallery.GetSyncRoot())
            {
                var content = gallery.LoadContent(false);
                GalleryImageBase img = null;

                    var siteUrls = new ImageUrlSet()
                                       {Original = Common.Utils.AbsoluteToVirtual(filepath, this.HttpContext)};
                    var editUrls = new ImageUrlSet()
                                       {Original = Common.Utils.AbsoluteToVirtual(filepath, this.HttpContext)};
                    var gllrUrls = new ImageUrlSet() {Original = gllrUrlHandler(filename)};

                    string extension = Path.GetExtension(filename);
                    string filenameonly = extension.Length > 0
                                              ? filename.Remove(filename.Length - extension.Length)
                                              : filename;

                    System.Drawing.Image originalImage = null;

                    //TODO: Implement async image resizing for performance
                    try
                    {
                        originalImage = System.Drawing.Image.FromFile(filepath);

                        //resize images for development
                        {
                            string editpath = Path.Combine(contentpath,
                                                           string.Format("{0}.lrgedit{1}", filenameonly, extension));
                            ResizeImage(originalImage, editpath, GalleryRuntime.EditedLargeImageSize);

                            editUrls.Large = Common.Utils.AbsoluteToVirtual(editpath, this.HttpContext);

                            content.SystemFilePathes.Add(editpath.Substring(rootpath.Length));
                        }
                        {
                            string editpath = Path.Combine(contentpath,
                                                           string.Format("{0}.smledit{1}", filenameonly, extension));
                            ResizeImage(originalImage, editpath, GalleryRuntime.EditedSmallImageSize);

                            editUrls.Small = Common.Utils.AbsoluteToVirtual(editpath, this.HttpContext);

                            content.SystemFilePathes.Add(editpath.Substring(rootpath.Length));
                        }

                    }
                    finally
                    {
                        if (originalImage != null)
                            originalImage.Dispose();
                    }

                try
                {
                    img = content.Images.SingleOrDefault(_ => _.ID == imageID);
                    if (img.ContentImage != null)
                    {
                        if(img.ContentImage.EditUrls!= null)
                        {
                            content.DeleteImages(img.ContentImage.EditUrls, this.HttpContext);
                        }
                        img.ContentImage.EditUrls = editUrls;
                    }

                    gallery.SaveContent(content, false);
                }
                catch (Exception ex)
                {
                    this.Logger.WriteError(ex);
                    File.Delete(filepath);
                    return message.CreateResponse(HttpStatusCode.InternalServerError);
                }
                var output = new UploadedImageContentResponse() { GalleryID = id.Value, ImageID = img.ID, ContentUrl = editUrls.Large};
                return message.CreateResponse<UploadedImageContentResponse>(HttpStatusCode.OK, output);
            }
        }
        public void DeleteImages(ImageUrlSet urls, HttpContextBase context)
        {
            Action<string> delHandler = delegate(string filepath)
            {
                if (string.IsNullOrEmpty(filepath))
                    return;

                var file = new FileInfo(filepath);

                if (file.Exists)
                {
                    try
                    {
                        file.Delete();
                    }
                    catch (Exception)
                    {
            #if DEBUG
                        //generate exception not to hide problems (for example file locks)
                        throw;
            #endif
                    }
                }
            };

            foreach (var vpath in new string[] { urls.Original, urls.Large, urls.Middle, urls.Small })
            {
                if (string.IsNullOrEmpty(vpath))
                    continue;

                string path = Corbis.Common.Utils.VirtualToAbsolute(vpath, context);
                delHandler(path);
                this.SystemFilePathes.Remove(this.SystemFilePathes.FirstOrDefault(path.EndsWith));
            }
        }
        public HttpResponseMessage UploadGalleryImage(HttpRequestMessage message,
            [System.Web.Http.FromUri, System.ComponentModel.DataAnnotations.Required]Nullable<int> id, [System.Web.Http.FromUri]string imageID)
        {
            if (this.HttpContext.Request.Files.Count != 1)
                return this.Request.CreateResponse(HttpStatusCode.NotAcceptable, "There are no files or more then one for uploading in the request");

            if (!id.HasValue)
                throw new Exception("Target gallery is not pointed. Query strin parameter 'id' is required");

            var gallery = GalleryRuntime.GetGallery(id.Value);
            var template = GalleryRuntime.GetTemplate(gallery.TemplateID);

            string contentpath = gallery.GetContentPath();
            string rootpath = gallery.GetDevPath();

            if (!Directory.Exists(contentpath))
                Directory.CreateDirectory(contentpath);

            var file = this.HttpContext.Request.Files[0];

            //TODO: CHANGE VALIDATE LOGIC
            if (GalleryRuntime.MaxImageSize.HasValue && GalleryRuntime.MaxImageSize.Value < file.ContentLength)
                return this.Request.CreateResponse<string>(HttpStatusCode.BadRequest, string.Format("Uploading file size is {0}byte. Max file size {1}bytes is exceeded", file.ContentLength, GalleryRuntime.MaxImageSize.Value));

            if (GalleryRuntime.MinImageSize.HasValue && file.ContentLength < GalleryRuntime.MinImageSize.Value)
                return this.Request.CreateResponse<string>(HttpStatusCode.BadRequest, string.Format("Uploading file size is {0}byte. Min file size is {1}bytes", file.ContentLength, GalleryRuntime.MaxImageSize.Value));

            string filename = file.FileName;
            string filepath = Path.Combine(contentpath, filename);

            if (File.Exists(filepath))
            {
                filepath = Common.Utils.GenerateFilePathForDuplicate(filepath);
                filename = Path.GetFileName(filepath);
            }

            //try to save original image
            try
            {
                file.SaveAs(filepath);
            }
            catch (Exception ex)
            {
                this.Logger.WriteError(ex, string.Format("Uploaded file cannot be saved to '{0}'", filepath));
                return this.Request.CreateResponse(HttpStatusCode.InternalServerError);
            }
            finally
            {
                file.InputStream.Close();
            }

            //this handler return gallery relative image url
            Common.ActionHandler<string, string> gllrUrlHandler =
                delegate(string fname)
                {
                    return string.Format("{0}/{1}", Common.Utils.GetRelativePath(GalleryRuntime.GetGalleryOutputPath(id.Value), contentpath).TrimEnd('\\').Replace('\\', '/'), fname);
                };

            lock (gallery.GetSyncRoot())
            {
                var content = gallery.LoadContent(false);

                var siteUrls = new ImageUrlSet() { Original = Common.Utils.AbsoluteToVirtual(filepath, this.HttpContext) };
                var editUrls = new ImageUrlSet() { Original = Common.Utils.AbsoluteToVirtual(filepath, this.HttpContext) };
                var gllrUrls = new ImageUrlSet() { Original = gllrUrlHandler(filename) };

                string extension = Path.GetExtension(filename);
                string filenameonly = extension.Length > 0 ? filename.Remove(filename.Length - extension.Length) : filename;

                System.Drawing.Image originalImage = null;

                //TODO: Implement async image resizing for performance
                try
                {
                    originalImage = System.Drawing.Image.FromFile(filepath);

                    //resize images for development
                    {
                        string editpath = Path.Combine(contentpath, string.Format("{0}.lrgedit{1}", filenameonly, extension));
                        ResizeImage(originalImage, editpath, GalleryRuntime.EditedLargeImageSize);

                        editUrls.Large = Common.Utils.AbsoluteToVirtual(editpath, this.HttpContext);

                        content.SystemFilePathes.Add(editpath.Substring(rootpath.Length));
                    }
                    {
                        string editpath = Path.Combine(contentpath, string.Format("{0}.smledit{1}", filenameonly, extension));
                        ResizeImage(originalImage, editpath, GalleryRuntime.EditedSmallImageSize);

                        editUrls.Small = Common.Utils.AbsoluteToVirtual(editpath, this.HttpContext);

                        content.SystemFilePathes.Add(editpath.Substring(rootpath.Length));
                    }

                    //images for galleries
                    foreach (var isize in template.GallerySettings.ImageSizes)
                    {
                        switch (isize.Type)
                        {
                            case GalleryImageSizes.Small:
                                {
                                    string smallpath = Path.Combine(contentpath, string.Format("{0}.sml{1}", filenameonly, extension));
                                    ResizeImage(originalImage, smallpath, new System.Drawing.Size(isize.Width, isize.Height));

                                    siteUrls.Small = Common.Utils.AbsoluteToVirtual(smallpath, this.HttpContext);
                                    gllrUrls.Small = gllrUrlHandler(Path.GetFileName(smallpath));
                                }
                                break;
                            case GalleryImageSizes.Middle:
                                {
                                    string middlepath = Path.Combine(contentpath, string.Format("{0}.mdl{1}", filenameonly, extension));
                                    ResizeImage(originalImage, middlepath, new System.Drawing.Size(isize.Width, isize.Height));

                                    siteUrls.Middle = Common.Utils.AbsoluteToVirtual(middlepath, this.HttpContext);
                                    gllrUrls.Middle = gllrUrlHandler(Path.GetFileName(middlepath));
                                }
                                break;
                            case GalleryImageSizes.Large:
                                {
                                    string largepath = Path.Combine(contentpath, string.Format("{0}.lrg{1}", filenameonly, extension));
                                    ResizeImage(originalImage, largepath, new System.Drawing.Size(isize.Width, isize.Height));

                                    siteUrls.Large = Common.Utils.AbsoluteToVirtual(largepath, this.HttpContext);
                                    gllrUrls.Large = gllrUrlHandler(Path.GetFileName(largepath));
                                }
                                break;
                            default:
                                throw new NotImplementedException();
                        }
                    }
                }
                finally
                {
                    if (originalImage != null)
                        originalImage.Dispose();
                }

                GalleryImageBase img = null;

                try
                {
                    if (string.IsNullOrEmpty(imageID))
                    {
                        if (content.Images.Count == 0)
                        {
                            var cimg = new GalleryCoverImage()
                            {
                                ID = string.Format("gallery-image_{0}", Guid.NewGuid().ToString("N")),
                                Name = filename,
                                Order = 1,
                                ImageSource = new GalleryImageSource() { Type = ImageSourceTypes.LocalFile, Source = filepath.Substring(GalleryRuntime.GetGalleryDevPath(id.Value).Length) },
                                GalleryUrls = gllrUrls,
                                SiteUrls = siteUrls,
                                EditUrls = editUrls
                            };

                            //TODO: we can get default values from gallery template
                            cimg.Headline = new CoverTextItem() { FontSize = 40 };
                            cimg.Standfirst = new CoverTextItem() { FontSize = 12 };
                            cimg.ContentImage = new GalleryImageContent();
                            cimg.ContentImage.TextContent = new CustomImageTextContent();
                            content.Images.Add(cimg);
                            img = cimg;
                        }
                        else
                        {
                            var cimg = new GalleryContentImage()
                            {
                                ID = string.Format("gallery-image_{0}", Guid.NewGuid().ToString("N")),
                                Name = filename,
                                Order = content.Images.Count + 1,
                                ImageSource = new GalleryImageSource() { Type = ImageSourceTypes.LocalFile, Source = filepath.Substring(GalleryRuntime.GetGalleryDevPath(id.Value).Length) },
                                GalleryUrls = gllrUrls,
                                SiteUrls = siteUrls,
                                EditUrls = editUrls
                            };
                            cimg.ContentImage = new GalleryImageContent();
                            cimg.ContentImage.TextContent = new EmptyTextContent();

                            content.Images.Add(cimg);
                            img = cimg;
                        }
                    }
                    else if (content.Images.Count != 0)
                    {
                        if (content.CoverImage.ID == imageID)
                        {
                            content.CoverImage.Name = filename;
                            content.CoverImage.ImageSource = new GalleryImageSource() { Type = ImageSourceTypes.LocalFile, Source = filepath.Substring(GalleryRuntime.GetGalleryDevPath(id.Value).Length) };
                            content.DeleteImages(content.CoverImage.GalleryUrls, this.HttpContext);
                            content.CoverImage.GalleryUrls = gllrUrls;
                            content.DeleteImages(content.CoverImage.SiteUrls, this.HttpContext);
                            content.CoverImage.SiteUrls = siteUrls;
                            content.DeleteImages(content.CoverImage.EditUrls, this.HttpContext);
                            content.CoverImage.EditUrls = editUrls;

                            img = content.CoverImage;
                        }
                        else
                        {
                            var item = content.Images.Where(x => x.ID == imageID).SingleOrDefault();

                            item.Name = filename;
                            item.ImageSource = new GalleryImageSource() { Type = ImageSourceTypes.LocalFile, Source = filepath.Substring(GalleryRuntime.GetGalleryDevPath(id.Value).Length) };
                            content.DeleteImages(item.GalleryUrls, this.HttpContext);
                            item.GalleryUrls = gllrUrls;
                            content.DeleteImages(item.SiteUrls, this.HttpContext);
                            item.SiteUrls = siteUrls;
                            content.DeleteImages(item.EditUrls, this.HttpContext);
                            item.EditUrls = editUrls;

                            img = item;
                        }
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }

                    //TODO: We must synchronize file updating
                    gallery.SaveContent(content, false);
                }
                catch (Exception ex)
                {
                    this.Logger.WriteError(ex);
                    File.Delete(filepath);
                    return message.CreateResponse(HttpStatusCode.InternalServerError);
                }

                var output = new UploadedImageResponse() { GalleryID = id.Value, ID = img.ID, Urls = img.SiteUrls, EditUrls = img.EditUrls, IsCover = img is GalleryCoverImage, FileName = img.Name, ImageID = imageID };
                return message.CreateResponse<UploadedImageResponse>(HttpStatusCode.OK, output);
            }
        }
        /// <summary>
        /// Initializes environment with data from configuration section
        /// </summary>
        /// <param name="configSection"></param>
        public static void Initialize(string configSection = null)
        {
            var section = CuratedGalleryEnvironmentSection.GetSection(configSection);

            //
            GalleryDevelopmentDirectory = GetAbsolutePath(section.Settings.GalleryDevelopmentDirectory);

            if (!Directory.Exists(GalleryDevelopmentDirectory))
                Directory.CreateDirectory(GalleryDevelopmentDirectory);

            //
            GalleryLiveDirectory = GetAbsolutePath(section.Settings.GalleryLiveDirectory);

            if (!Directory.Exists(GalleryLiveDirectory))
                Directory.CreateDirectory(GalleryLiveDirectory);

            //
            MaxImageSize = section.Settings.MaxImageSize;
            MinImageSize = section.Settings.MinImageSize;

            EditedLargeImageSize = new Size() { Width = section.Settings.ImageEditMode.LargeImageSizePx.Width, Height = section.Settings.ImageEditMode.LargeImageSizePx.Height };
            EditedSmallImageSize = new Size() { Width = section.Settings.ImageEditMode.SmallImageSizePx.Width, Height = section.Settings.ImageEditMode.SmallImageSizePx.Height };

            //
            SharedDirectory = GetAbsolutePath(section.Settings.SharedDirectory);

            if (!Directory.Exists(SharedDirectory))
                Directory.CreateDirectory(SharedDirectory);

            //
            TemplateDirectory = GetAbsolutePath(section.Settings.TemplateDirectory);

            if (!Directory.Exists(TemplateDirectory))
                Directory.CreateDirectory(TemplateDirectory);

            //
            TemporaryDirectory = GetAbsolutePath(section.Settings.TemporaryDirectory);

            if (!Directory.Exists(TemporaryDirectory))
                Directory.CreateDirectory(TemporaryDirectory);

            //
            DefaultTemplateImageUrl = new ImageUrlSet() { Large = section.Settings.DefaultTemplateImageUrl };

            if (!Directory.Exists(TemplateDirectory))
                Directory.CreateDirectory(TemplateDirectory);
        }