// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.TestCommon;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.Extensions.Localization;
using Moq;
using Xunit;

namespace Microsoft.AspNetCore.Mvc.Rendering
{
    public class HtmlHelperDisplayExtensionsTest
    {
        [Fact]
        public void DisplayHelpers_FindsModel_WhenViewDataIsNotSet()
        {
            // Arrange
            var expected = $"<div class=\"HtmlEncode[[display-label]]\">HtmlEncode[[SomeProperty]]</div>{Environment.NewLine}" +
                $"<div class=\"HtmlEncode[[display-field]]\">HtmlEncode[[PropValue]]</div>{Environment.NewLine}";
            var model = new SomeModel
            {
                SomeProperty = "PropValue"
            };
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.Display(expression: string.Empty);
            var displayNullResult = helper.Display(expression: null);   // null is another alias for current model
            var displayForResult = helper.DisplayFor(m => m);
            var displayForModelResult = helper.DisplayForModel();

            // Assert
            Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayResult));
            Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayNullResult));
            Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayForResult));
            Assert.Equal(expected, HtmlContentUtilities.HtmlContentToString(displayForModelResult));
        }

        [Fact]
        public void Display_UsesAdditionalViewData()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.Display(expression: "SomeProperty", additionalViewData: new { SomeProperty = "ViewDataValue" });

            // Assert
            Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void Display_UsesTemplateName()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", Mock.Of<IView>()))
                .Verifiable();
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.Display(expression: "SomeProperty", templateName: "SomeTemplate");

            // Assert
            viewEngine.Verify();
        }

        public static TheoryData<FormatModel, string> EnumFormatModels
        {
            get
            {
                return new TheoryData<FormatModel, string>
                {
                    {
                        new FormatModel{ FormatProperty = Status.Created },
                        "Value: CreatedKey"
                    },
                    {
                        new FormatModel { FormatProperty = Status.Done },
                        "Value: Done"
                    }
                };
            }
        }

        public static TheoryData<FormatModel, string> EnumUnformattedModels
        {
            get
            {
                return new TheoryData<FormatModel, string>
                {
                    {
                        new FormatModel {NonFormatProperty = Status.Created },
                        "CreatedKey"
                    },
                    {
                        new FormatModel {NonFormatProperty = Status.Done },
                        "Done"
                    }
                };
            }
        }

        [Theory]
        [MemberData(nameof(EnumUnformattedModels))]
        public void Display_UsesTemplateUnFormatted(FormatModel model, string expectedResult)
        {
            // Arrange
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.FormattedModelValue.ToString()))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/Status", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("Status", view.Object))
                .Verifiable();
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayFor(x => x.NonFormatProperty);

            // Assert
            Assert.Equal(expectedResult, HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Theory]
        [MemberData(nameof(EnumFormatModels))]
        public void Display_UsesTemplateFormatted(FormatModel model, string expectedResult)
        {
            // Arrange
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.FormattedModelValue.ToString()))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/Status", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("Status", view.Object))
                .Verifiable();
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayFor(x => x.FormatProperty);

            // Assert
            Assert.Equal(expectedResult, HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void Display_UsesTemplateNameAndAdditionalViewData()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.Display(
                expression: "SomeProperty",
                templateName: "SomeTemplate",
                additionalViewData: new { SomeProperty = "ViewDataValue" });

            // Assert
            Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void Display_UsesTemplateNameAndHtmlFieldName()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.Display(
                expression: "SomeProperty",
                templateName: "SomeTemplate",
                htmlFieldName: "SomeField");

            // Assert
            Assert.Equal("SomeField", HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void DisplayFor_UsesAdditionalViewData()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayFor(expression: m => m.SomeProperty, additionalViewData: new { SomeProperty = "ViewDataValue" });

            // Assert
            Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void DisplayFor_UsesTemplateName()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", Mock.Of<IView>()))
                .Verifiable();
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayFor(expression: m => m.SomeProperty, templateName: "SomeTemplate");

            // Assert
            viewEngine.Verify();
        }

        [Fact]
        public void DisplayFor_UsesTemplateNameAndAdditionalViewData()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayFor(
                expression: m => m.SomeProperty,
                templateName: "SomeTemplate",
                additionalViewData: new { SomeProperty = "ViewDataValue" });

            // Assert
            Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void DisplayFor_EnumProperty_IStringLocalizedValue()
        {
            // Arrange
            var model = new StatusModel
            {
                Status = Status.Created
            };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.FormattedModelValue.ToString()))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/Status", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));

            var stringLocalizer = new Mock<IStringLocalizer>(MockBehavior.Strict);
            stringLocalizer
                .Setup(s => s["CreatedKey"])
                .Returns<string>((key) =>
                {
                    return new LocalizedString(key, "created from IStringLocalizer");
                });
            var stringLocalizerFactory = new Mock<IStringLocalizerFactory>();
            stringLocalizerFactory
                .Setup(s => s.Create(typeof(Status)))
                .Returns(stringLocalizer.Object);

            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object, stringLocalizerFactory.Object);

            // Act
            var displayResult = helper.DisplayFor(m => m.Status);

            // Assert
            Assert.Equal("created from IStringLocalizer", HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void DisplayFor_EnumProperty_ResourceTypeLocalizedValue()
        {
            // Arrange
            var model = new StatusModel
            {
                Status = Status.Faulted
            };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.FormattedModelValue.ToString()))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/Status", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayFor(m => m.Status);

            // Assert
            Assert.Equal("Faulted from ResourceType", HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void DisplayFor_UsesTemplateNameAndHtmlFieldName()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayFor(
                expression: m => m.SomeProperty,
                templateName: "SomeTemplate",
                htmlFieldName: "SomeField");

            // Assert
            Assert.Equal("SomeField", HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void DisplayForModel_UsesAdditionalViewData()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayForModel(additionalViewData: new { SomeProperty = "ViewDataValue" });

            // Assert
            Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void DisplayForModel_UsesTemplateName()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", Mock.Of<IView>()))
                .Verifiable();
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayForModel(templateName: "SomeTemplate");

            // Assert
            viewEngine.Verify();
        }

        [Fact]
        public void DisplayForModel_UsesTemplateNameAndAdditionalViewData()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData["SomeProperty"].ToString()))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayForModel(
                templateName: "SomeTemplate",
                additionalViewData: new { SomeProperty = "ViewDataValue" });

            // Assert
            Assert.Equal("ViewDataValue", HtmlContentUtilities.HtmlContentToString(displayResult));
        }

        [Fact]
        public void DisplayForModel_UsesTemplateNameAndHtmlFieldName()
        {
            // Arrange
            var model = new SomeModel { SomeProperty = "ModelValue" };
            var view = new Mock<IView>();
            view.Setup(v => v.RenderAsync(It.IsAny<ViewContext>()))
                .Callback((ViewContext v) => v.Writer.WriteAsync(v.ViewData.TemplateInfo.HtmlFieldPrefix))
                .Returns(Task.FromResult(0));
            var viewEngine = new Mock<ICompositeViewEngine>(MockBehavior.Strict);
            viewEngine
                .Setup(v => v.GetView(/*executingFilePath*/ null, It.IsAny<string>(), /*isMainPage*/ false))
                .Returns(ViewEngineResult.NotFound(string.Empty, Enumerable.Empty<string>()));
            viewEngine
                .Setup(v => v.FindView(It.IsAny<ActionContext>(), "DisplayTemplates/SomeTemplate", /*isMainPage*/ false))
                .Returns(ViewEngineResult.Found("SomeView", view.Object));
            var helper = DefaultTemplatesUtilities.GetHtmlHelper(model, viewEngine.Object);

            // Act
            var displayResult = helper.DisplayForModel(
                templateName: "SomeTemplate",
                htmlFieldName: "SomeField");

            // Assert
            Assert.Equal("SomeField", HtmlContentUtilities.HtmlContentToString(displayResult));
        }


        public class StatusResource
        {
            public static string FaultedKey { get { return "Faulted from ResourceType"; } }
        }

        public enum Status : byte
        {
            [Display(Name = "CreatedKey")]
            Created,
            [Display(Name = "FaultedKey", ResourceType = typeof(StatusResource))]
            Faulted,
            Done
        }

        public class FormatModel
        {
            [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "Value: {0}")]
            public Status FormatProperty { get; set; }

            public Status NonFormatProperty { get; set; }
        }

        private class SomeModel
        {
            public string SomeProperty { get; set; }
        }

        private class StatusModel
        {
            public Status Status { get; set; }
        }
    }
}
