﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.Editor.CSharp.DocumentationComments;
using Microsoft.CodeAnalysis.Editor.UnitTests.DocumentationComments;
using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.Commanding;
using Microsoft.VisualStudio.Text.Editor.Commanding.Commands;
using Roslyn.Test.Utilities;
using Xunit;

namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.DocumentationComments
{
    [Trait(Traits.Feature, Traits.Features.XmlTagCompletion)]
    public class XmlTagCompletionTests : AbstractXmlTagCompletionTests
    {
        private protected override IChainedCommandHandler<TypeCharCommandArgs> CreateCommandHandler(TestWorkspace workspace)
            => workspace.ExportProvider.GetCommandHandler<XmlTagCompletionCommandHandler>(nameof(XmlTagCompletionCommandHandler), ContentTypeNames.CSharpContentType);

        private protected override TestWorkspace CreateTestWorkspace(string initialMarkup)
            => TestWorkspace.CreateCSharp(initialMarkup);

        [WpfFact]
        public void SimpleTagCompletion()
        {
            var text = @"
/// <goo$$
class c { }";

            var expected = @"
/// <goo>$$</goo>
class c { }";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void NestedTagCompletion()
        {
            var text = @"
/// <summary>
/// <goo$$
/// </summary>
class c { }";

            var expected = @"
/// <summary>
/// <goo>$$</goo>
/// </summary>
class c { }";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void CompleteBeforeIncompleteTag()
        {
            var text = @"
/// <goo$$
/// </summary>
class c { }";

            var expected = @"
/// <goo>$$</goo>
/// </summary>
class c { }";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void NotEmptyElement()
        {
            var text = @"
/// <$$
class c { }";

            var expected = @"
/// <>$$
class c { }";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void NotAlreadyCompleteTag()
        {
            var text = @"
/// <goo$$</goo>
class c { }";

            var expected = @"
/// <goo>$$</goo>
class c { }";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void NotAlreadyCompleteTag2()
        {
            var text = @"
/// <goo$$
///
/// </goo>
class c { }";

            var expected = @"
/// <goo>$$
///
/// </goo>
class c { }";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void SimpleSlashCompletion()
        {
            var text = @"
/// <goo><$$
class c { }";

            var expected = @"
/// <goo></goo>$$
class c { }";

            Verify(text, expected, '/');
        }

        [WpfFact]
        public void NestedSlashTagCompletion()
        {
            var text = @"
/// <summary>
/// <goo><$$
/// </summary>
class c { }";

            var expected = @"
/// <summary>
/// <goo></goo>$$
/// </summary>
class c { }";

            Verify(text, expected, '/');
        }

        [WpfFact]
        public void SlashCompleteBeforeIncompleteTag()
        {
            var text = @"
/// <goo><$$
/// </summary>
class c { }";

            var expected = @"
/// <goo></goo>$$
/// </summary>
class c { }";

            Verify(text, expected, '/');
        }

        [WpfFact]
        public void SlashNotEmptyElement()
        {
            var text = @"
/// <><$$
class c { }";

            var expected = @"
/// <></$$
class c { }";

            Verify(text, expected, '/');
        }

        [WpfFact]
        public void SlashNotAlreadyCompleteTag()
        {
            var text = @"
/// <goo><$$goo>
class c { }";

            var expected = @"
/// <goo></$$goo>
class c { }";

            Verify(text, expected, '/');
        }

        [WpfFact]
        public void SlashNotAlreadyCompleteTag2()
        {
            var text = @"
/// <goo>
///
/// <$$goo>
class c { }";

            var expected = @"
/// <goo>
///
/// </$$goo>
class c { }";

            Verify(text, expected, '/');
        }

        [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/638800")]
        public void NestedIdenticalTags()
        {
            var text = @"
/// <goo><goo$$</goo>
class c { }";

            var expected = @"
/// <goo><goo>$$</goo></goo>
class c { }";

            Verify(text, expected, '>');
        }

        [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/638800")]
        public void MultipleNestedIdenticalTags()
        {
            var text = @"
/// <goo><goo><goo$$</goo></goo>
class c { }";

            var expected = @"
/// <goo><goo><goo>$$</goo></goo></goo>
class c { }";

            Verify(text, expected, '>');
        }

        [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/638235")]
        public void SlashNotIfCloseTagFollows()
        {
            var text = @"
/// <summary>
/// <$$
/// </summary>
class c { }";

            var expected = @"
/// <summary>
/// </$$
/// </summary>
class c { }";

            Verify(text, expected, '/');
        }

        [WpfFact]
        public void TestSimpleTagCompletion()
        {
            var text = @"
/// <goo$$
class C {}";

            var expected = @"
/// <goo>$$</goo>
class C {}";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void TestNestedTagCompletion()
        {
            var text = @"
/// <summary>
/// <goo$$
/// </summary>
class C {}";

            var expected = @"
/// <summary>
/// <goo>$$</goo>
/// </summary>
class C {}";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void TestCompleteBeforeIncompleteTag()
        {
            var text = @"
/// <goo$$
/// </summary>
class C {}";

            var expected = @"
/// <goo>$$</goo>
/// </summary>
class C {}";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void TestNotEmptyElement()
        {
            var text = @"
/// <$$
class C {}";

            var expected = @"
/// <>$$
class C {}";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void TestNotAlreadyCompleteTag()
        {
            var text = @"
/// <goo$$</goo>
class C {}";

            var expected = @"
/// <goo>$$</goo>
class C {}";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void TestNotAlreadyCompleteTag2()
        {
            var text = @"
/// <goo$$
///
/// </goo>
class C {}";

            var expected = @"
/// <goo>$$
///
/// </goo>
class C {}";

            Verify(text, expected, '>');
        }

        [WpfFact]
        public void TestNotOutsideDocComment()
        {
            var text = @"
class C
{
    private int z = <goo$$
}";

            var expected = @"
class C
{
    private int z = <goo>$$
}";

            Verify(text, expected, '>');
        }

        [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/638235")]
        public void TestNotCloseClosedTag()
        {
            var text = @"
/// <summary>
/// <$$
/// </summary>
class C {}";

            var expected = @"
/// <summary>
/// </$$
/// </summary>
class C {}";

            Verify(text, expected, '/');
        }
    }
}
