// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

using System;
using System.Collections.Generic;
using Org.Apache.REEF.Common.Tasks;
using Org.Apache.REEF.Examples.Tasks.HelloTask;
using Org.Apache.REEF.Tang.Annotations;
using Org.Apache.REEF.Tang.Examples;
using Org.Apache.REEF.Tang.Exceptions;
using Org.Apache.REEF.Tang.Implementations.Tang;
using Org.Apache.REEF.Tang.Interface;
using Org.Apache.REEF.Tang.Types;
using Org.Apache.REEF.Tang.Util;
using Xunit;

namespace Org.Apache.REEF.Tang.Tests.ClassHierarchy
{
    public class TestClassHierarchy
    {
        public IClassHierarchy ns = null;

        public TestClassHierarchy()
        {
            if (ns == null)
            {
                ns = TangFactory.GetTang().GetClassHierarchy(new string[] { FileNames.Examples, FileNames.Common, FileNames.Tasks });
            }
        }

        [Fact]
        public void TestString()
        {
            INode n = null;
            try
            {
                n = ns.GetNode("System");
            }
            catch (ApplicationException)
            {
            }
            catch (NameResolutionException)
            {
            }
            Assert.Null(n);

            Assert.NotNull(ns.GetNode(typeof(string).AssemblyQualifiedName));

            string msg = null;  
            try
            {
                ns.GetNode("org.apache");
                msg = "Didn't get expected exception";
            }
            catch (ApplicationException)
            {
            }
            catch (NameResolutionException)
            {
            }
            Assert.True(msg == null, msg);
        }

        [Fact]
        public void TestInt()
        {
            INode n = null;
            try
            {
                n = ns.GetNode("System");
            }
            catch (ApplicationException)
            {
            }
            catch (NameResolutionException)
            {
            }
            Assert.Null(n);

            Assert.NotNull(ns.GetNode(typeof(int).AssemblyQualifiedName));

            string msg = null;      
            try
            {
                ns.GetNode("org.apache");
                msg = "Didn't get expected exception";
            }
            catch (ApplicationException)
            {
            }
            catch (NameResolutionException)
            {
            }
            Assert.True(msg == null, msg);        
        }

        [Fact]
        public void TestSimpleConstructors()
        {
            IClassNode cls = (IClassNode)ns.GetNode(typeof(SimpleConstructors).AssemblyQualifiedName);
            Assert.True(cls.GetChildren().Count == 0);
            IList<IConstructorDef> def = cls.GetInjectableConstructors();
            Assert.Equal(3, def.Count);
        }

        [Fact]
        public void TestTimer()
        {
            IClassNode timerClassNode = (IClassNode)ns.GetNode(typeof(Timer).AssemblyQualifiedName);
            INode secondNode = ns.GetNode(typeof(Timer.Seconds).AssemblyQualifiedName);
            Assert.Equal(secondNode.GetFullName(), ReflectionUtilities.GetAssemblyQualifiedName(typeof(Timer.Seconds)));
        }

        [Fact]
        public void TestNamedParameterConstructors()
        {
            var node = ns.GetNode(typeof(NamedParameterConstructors).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), ReflectionUtilities.GetAssemblyQualifiedName(typeof(NamedParameterConstructors)));
        }

        [Fact]
        public void TestArray()
        {
            Type t = (new string[0]).GetType();
            INode node = ns.GetNode(t.AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), t.AssemblyQualifiedName);
        }

        [Fact]
        public void TestRepeatConstructorArg()
        {
            TestNegativeCase(typeof(RepeatConstructorArg),
                "Repeated constructor parameter detected.  Cannot inject constructor RepeatConstructorArg(int,int).");
        }

        [Fact]
        public void TestRepeatConstructorArgClasses()
        {
            TestNegativeCase(typeof(RepeatConstructorArgClasses),
                "Repeated constructor parameter detected.  Cannot inject constructor RepeatConstructorArgClasses(A, A).");
        }

        [Fact]
        public void testLeafRepeatedConstructorArgClasses()
        {
            INode node = ns.GetNode(typeof(LeafRepeatedConstructorArgClasses).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), typeof(LeafRepeatedConstructorArgClasses).AssemblyQualifiedName);
        }

        [Fact]
        public void TestNamedRepeatConstructorArgClasses()
        {
            INode node = ns.GetNode(typeof(NamedRepeatConstructorArgClasses).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), typeof(NamedRepeatConstructorArgClasses).AssemblyQualifiedName);
        }

        [Fact]
        public void TestResolveDependencies() 
        {
            ns.GetNode(typeof(SimpleConstructors).AssemblyQualifiedName);
            Assert.NotNull(ns.GetNode(typeof(string).AssemblyQualifiedName));
        }

        [Fact]
        public void TestDocumentedLocalNamedParameter()
        {
            var node = ns.GetNode(typeof(DocumentedLocalNamedParameter).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), ReflectionUtilities.GetAssemblyQualifiedName(typeof(DocumentedLocalNamedParameter)));
        }

        [Fact]
        public void TestNamedParameterTypeMismatch()
        {
            TestNegativeCase(typeof(NamedParameterTypeMismatch),
                "Named parameter type mismatch in NamedParameterTypeMismatch. Constructor expects a System.String but Foo is a System.Int32.");
        }

        [Fact]
        public void TestUnannotatedName()
        {
            TestNegativeCase(typeof(UnannotatedName),
                "Named parameter UnannotatedName is missing its [NamedParameter] attribute.");
        }

        [Fact]
        public void TestAnnotatedNotName()
        {
            TestNegativeCase(typeof(AnnotatedNotName),
                "Found illegal [NamedParameter] AnnotatedNotName does not implement Name<T>.");
        }

        [Fact]
        public void TestAnnotatedNameWrongInterface()
        {
            TestNegativeCase(typeof(AnnotatedNameWrongInterface),
                "Found illegal [NamedParameter] AnnotatedNameWrongInterface does not implement Name<T>.");
        }

        [Fact]
        public void TestAnnotatedNameMultipleInterfaces()
        {
            TestNegativeCase(typeof(AnnotatedNameMultipleInterfaces),
                "Named parameter Org.Apache.REEF.Tang.Implementation.AnnotatedNameMultipleInterfaces implements multiple interfaces.  It is only allowed to implement Name<T>.");
        }

        [Fact]
        public void TestUnAnnotatedNameMultipleInterfaces()
        {
            TestNegativeCase(typeof(UnAnnotatedNameMultipleInterfaces),
                "Named parameter Org.Apache.REEF.Tang.Implementation.UnAnnotatedNameMultipleInterfaces is missing its @NamedParameter annotation.");
        }

        [Fact]
        public void TestNameWithConstructor()
        {
            TestNegativeCase(typeof(NameWithConstructor),
                "Named parameter Org.Apache.REEF.Tang.Implementation.NameWithConstructor has a constructor.  Named parameters must not declare any constructors.");
        }

        [Fact]
        public void TestNameWithZeroArgInject()
        {
            TestNegativeCase(typeof(NameWithZeroArgInject),
                "Named parameter Org.Apache.REEF.Tang.Implementation.NameWithZeroArgInject has an injectable constructor.  Named parameters must not declare any constructors.");
        }

        [Fact]
        public void TestInjectNonStaticLocalArgClass()
        {
            var node = ns.GetNode(typeof(InjectNonStaticLocalArgClass).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), typeof(InjectNonStaticLocalArgClass).AssemblyQualifiedName);
        }

        [Fact]
        public void TestInjectNonStaticLocalType()
        {
            var node = ns.GetNode(typeof(InjectNonStaticLocalType).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), typeof(InjectNonStaticLocalType).AssemblyQualifiedName);
        }

        [Fact]
        public void TestOKShortNames()
        {
            var node = ns.GetNode(typeof(ShortNameFooA).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), typeof(ShortNameFooA).AssemblyQualifiedName);
        }

        public void TestConflictingShortNames()
        {
            string msg = null;
            try
            {
                var nodeA = ns.GetNode(typeof(ShortNameFooA).AssemblyQualifiedName);
                var nodeB = ns.GetNode(typeof(ShortNameFooB).AssemblyQualifiedName);
                msg = 
                    "ShortNameFooA and ShortNameFooB have the same short name" +
                    nodeA.GetName() + nodeB.GetName();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            Assert.True(msg == null, msg);
        }

        [Fact]
        public void TestRoundTripInnerClassNames()
        {
            INode node = ns.GetNode(typeof(Nested.Inner).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), typeof(Nested.Inner).AssemblyQualifiedName);
        }

        [Fact]
        public void TestRoundTripAnonInnerClassNames()
        {
            INode node1 = ns.GetNode(typeof(AnonNested.X1).AssemblyQualifiedName);
            INode node2 = ns.GetNode(typeof(AnonNested.Y1).AssemblyQualifiedName);
            Assert.NotEqual(node1.GetFullName(), node2.GetFullName());

            Type t1 = ReflectionUtilities.GetTypeByName(node1.GetFullName());
            Type t2 = ReflectionUtilities.GetTypeByName(node2.GetFullName());

            Assert.NotSame(t1, t2);
        }

        [Fact]
        public void TestNameCantBindWrongSubclassAsDefault()
        {
            TestNegativeCase(typeof(BadName),
            "class org.apache.reef.tang.implementation.BadName defines a default class Int32 with a type that does not extend of its target's type string");
        }

        [Fact]
        public void TestNameCantBindWrongSubclassOfArgumentAsDefault()
        {
            TestNegativeCase(typeof(BadNameForGeneric),
                        "class BadNameForGeneric defines a default class Int32 with a type that does not extend of its target's string in ISet<string>");
        }

        [Fact]
        public void TestNameCantBindSubclassOfArgumentAsDefault()
        {
            ns = TangFactory.GetTang().GetClassHierarchy(new string[] { FileNames.Examples, FileNames.Common, FileNames.Tasks });
            INode node = ns.GetNode(typeof(GoodNameForGeneric).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), typeof(GoodNameForGeneric).AssemblyQualifiedName);
        }

        [Fact]
        public void TestInterfaceCantBindWrongImplAsDefault()
        {
            TestNegativeCase(typeof(IBadIfaceDefault),
                             "interface IBadIfaceDefault declares its default implementation to be non-subclass class string");
        }

        private void TestNegativeCase(Type clazz, string message)
        {
            string msg = null;
            try
            {
                var node = ns.GetNode(typeof(IBadIfaceDefault).AssemblyQualifiedName);
                msg = message + node.GetName();
            }
            catch (Exception)
            {
            }
            Assert.True(msg == null, msg);
        }

        [Fact]
        public void TestParseableDefaultClassNotOK()
        {
            TestNegativeCase(typeof(BadParsableDefaultClass),
                 "Named parameter BadParsableDefaultClass defines default implementation for parsable type System.string");
        }

        [Fact]
        public void testGenericTorture1()
        {
            g(typeof(GenericTorture1));
        }
        [Fact]
        public void testGenericTorture2()
        {
            g(typeof(GenericTorture2));
        }
        [Fact]
        public void testGenericTorture3()
        {
            g(typeof(GenericTorture3));
        }
        [Fact]
        public void testGenericTorture4()
        {
            g(typeof(GenericTorture4));
        }

        public string s(Type t)
        {
            return ReflectionUtilities.GetAssemblyQualifiedName(t);
        }
        public INode g(Type t)
        {
            INode n = ns.GetNode(s(t)); 
            Assert.NotNull(n);
            return n;
        }

        [Fact]
        public void TestHelloTaskNode()
        {
            var node = ns.GetNode(typeof(HelloTask).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), ReflectionUtilities.GetAssemblyQualifiedName(typeof(HelloTask)));
        }

        [Fact]
        public void TestITackNode()
        {
            var node = ns.GetNode(typeof(ITask).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), ReflectionUtilities.GetAssemblyQualifiedName(typeof(ITask)));
        }

        [Fact]
        public void TestNamedParameterIdentifier()
        {
            var node = ns.GetNode(typeof(TaskConfigurationOptions.Identifier).AssemblyQualifiedName);
            Assert.Equal(node.GetFullName(), ReflectionUtilities.GetAssemblyQualifiedName(typeof(TaskConfigurationOptions.Identifier)));
        }
        [Fact]
        public void TestInterface()
        {
            g(typeof(A));
            g(typeof(MyInterface<int>));
            g(typeof(MyInterface<string>));
            g(typeof(B));

            ITang tang = TangFactory.GetTang();
            ICsConfigurationBuilder cb = tang.NewConfigurationBuilder();

            cb.BindImplementation(GenericType<MyInterface<string>>.Class, GenericType<MyImplString>.Class);
            cb.BindImplementation(GenericType<MyInterface<int>>.Class, GenericType<MyImplInt>.Class);
            IConfiguration conf = cb.Build();
            IInjector i = tang.NewInjector(conf);

            var a = (A)i.GetInstance(typeof(A));
            var implString = (MyImplString)i.GetInstance(typeof(MyImplString));
            var implInt = (MyImplString)i.GetInstance(typeof(MyImplString));
            var b = (B)i.GetInstance(typeof(B));
            var c = (C)i.GetInstance(typeof(C));

            Assert.NotNull(a);
            Assert.NotNull(implString);
            Assert.NotNull(implInt);
            Assert.NotNull(b);
            Assert.NotNull(c);
        }

        // See REEF-1276
        [Fact]
        public void TestInjectableClassWithParameterAnnotationThrowsMeaningfulException()
        {
            ITang tang = TangFactory.GetTang();
            IInjector i = tang.NewInjector(tang.NewConfigurationBuilder().Build());

            Action injection = () => i.GetInstance(typeof(ClazzA));
            Assert.Throws<ArgumentException>(injection);
        }
    }

    [NamedParameter]
    class GenericTorture1 : Name<ISet<string>> 
    {
    }
    [NamedParameter]
    class GenericTorture2 : Name<ISet<ISet<string>>>
    {
    }
    [NamedParameter]
    class GenericTorture3 : Name<IDictionary<ISet<string>, ISet<string>>>
    {
    }
    [NamedParameter]
    class GenericTorture4 : Name<IDictionary<string, string>>
    {
    }

    public interface MyInterface<T>
    {
    }

    public class RepeatConstructorArg
    {
        [Inject]
        public RepeatConstructorArg(int x, int y)
        {
        }
    }

    public class RepeatConstructorArgClasses
    {
        [Inject]
        public RepeatConstructorArgClasses(A x, A y)
        {
        }
    }

    public class A : MyInterface<int>, MyInterface<string>
    {
        [Inject]
        A()
        {
        }
    }

    public class MyImplString : MyInterface<string>
    {
        [Inject]
        public MyImplString()
        {
        }
    }

    public class B
    {
        [Inject]
        public B(MyInterface<string> b)
        {
        }
    }

    public class MyImplInt : MyInterface<int>
    {
        [Inject]
        public MyImplInt()
        {
        }
    }
    public class C
    {
        [Inject]
        public C(MyInterface<int> b)
        {
        }
    }
    public class LeafRepeatedConstructorArgClasses
    {
        public static class A
        {
            public class AA
            {
            }
        }

        public static class B
        {
            public class AA
            {
            }
        }

        public class C
        {
            [Inject]
            public C(A.AA a, B.AA b)
            {
            }
        }
    }

    class D
    {        
    }
    [NamedParameter]
    class D1 : Name<D> 
    {
    }

    [NamedParameter]
    class D2 : Name<D> 
    {
    }

    class NamedRepeatConstructorArgClasses 
    {
        [Inject]
        public NamedRepeatConstructorArgClasses([Parameter(typeof(D1))] D x, [Parameter(typeof(D2))] D y) 
        {
        }
    }

    class NamedParameterTypeMismatch 
    {
        [NamedParameter(Documentation = "doc.stuff", DefaultValue = "1")]
        class Foo : Name<int> 
        {
        }

        [Inject]
        public NamedParameterTypeMismatch([Parameter(Value = typeof(Foo))] string s) 
        {
        }
    }

    class UnannotatedName : Name<string> 
    {
    }

    interface I1 
    {
    }

    [NamedParameter(Documentation = "c")]
    class AnnotatedNotName 
    {
    }

    [NamedParameter(Documentation = "c")]
    class AnnotatedNameWrongInterface : I1 
    {
    }

    class UnAnnotatedNameMultipleInterfaces : Name<object>, I1 
    {
    }

    [NamedParameter(Documentation = "c")]
    class AnnotatedNameMultipleInterfaces : Name<object>, I1 
    {
    }

    [NamedParameter(Documentation = "c")]
    class NameWithConstructor : Name<object> 
    {
        private NameWithConstructor(int i) 
        {
        }
    }

    [NamedParameter]
    class NameWithZeroArgInject : Name<object> 
    {
        [Inject]
        public NameWithZeroArgInject() 
        {
        }
    }

    class InjectNonStaticLocalArgClass
    {
        class NonStaticLocal
        {
        }

        [Inject]
        InjectNonStaticLocalArgClass(NonStaticLocal x)
        {
        }
    }

    class InjectNonStaticLocalType
    {
        class NonStaticLocal
        {
            [Inject]
            NonStaticLocal(NonStaticLocal x)
            {
            }
        }
    }

    [NamedParameter(ShortName = "foo")]
    public class ShortNameFooA : Name<string>
    {
    }

    // when same short name is used, exception would throw when building the class hierarchy
    [NamedParameter(ShortName = "foo")]
    public class ShortNameFooB : Name<int>
    {
    }

    class Nested
    {
        public class Inner
        {
        }
    }

    class AnonNested 
    {
        public interface X 
        {
        }

        public class X1 : X
        {
            // int i;
        }

        public class Y1 : X
        {
            // int j;
        }

        public static X XObj = new X1();
        public static X YObj = new Y1();
    }

    // Negative case: Int32 doesn't match string
    [NamedParameter(DefaultClass = typeof(Int32))]
    class BadName : Name<string>
    {        
    }

    // Negative case: Int32 doesn't match string in the ISet
    [NamedParameter(DefaultClass = typeof(Int32))]
    class BadNameForGeneric : Name<ISet<string>>
    {
    }

    // Positive case: type matched. ISet is not in parsable list
    [NamedParameter(DefaultClass = typeof(string))]
    class GoodNameForGeneric : Name<ISet<string>>
    {
    }

    [DefaultImplementation(typeof(string))]
    interface IBadIfaceDefault
    {        
    }

    // negative case: type matched. However, string is in the parsable list and DefaultClass is not null. 
    [NamedParameter(DefaultClass = typeof(string))]
    class BadParsableDefaultClass : Name<string>
    {        
    }

    // ClazzB is injectable and does not need the Parameter annotation in the ClazzA constructor
    class ClazzA
    {
        private ClazzB objectB;

        public class ClazzB 
        {
            [Inject]
            public ClazzB()
            {
            }
        }

        [Inject]
        public ClazzA([Parameter(typeof(ClazzB))] ClazzB objectB)
        {
            this.objectB = objectB;
        }
    }
 }