//
// Copyright (c) ZeroC, Inc. All rights reserved.
//

using System;

namespace Ice
{
    namespace servantLocator
    {
        public sealed class ServantLocatorI : Ice.ServantLocator
        {
            public ServantLocatorI(String category)
            {
                _category = category;
                _deactivated = false;
                _requestId = -1;
            }

            ~ServantLocatorI()
            {
                lock(this)
                {
                    test(_deactivated);
                }
            }

            private static void test(bool b)
            {
                if(!b)
                {
                    throw new System.Exception();
                }
            }

            public Ice.Object locate(Ice.Current current, out object cookie)
            {
                lock(this)
                {
                    test(!_deactivated);
                }

                test(current.id.category.Equals(_category) || _category.Length == 0);

                if(current.id.name.Equals("unknown"))
                {
                    cookie = null;
                    return null;
                }

                if(current.id.name.Equals("invalidReturnValue") || current.id.name.Equals("invalidReturnType"))
                {
                    cookie = null;
                    return null;
                }

                test(current.id.name.Equals("locate") || current.id.name.Equals("finished"));
                if(current.id.name.Equals("locate"))
                {
                    exception(current);
                }

                //
                // Ensure locate() is only called once per request.
                //
                test(_requestId == -1);
                _requestId = current.requestId;

                cookie = new CookieI();

                return new TestI();
            }

            public void finished(Ice.Current current, Ice.Object servant, System.Object cookie)
            {
                lock(this)
                {
                    test(!_deactivated);
                }

                //
                // Ensure finished() is only called once per request.
                //
                test(_requestId == current.requestId);
                _requestId = -1;

                test(current.id.category.Equals(_category) || _category.Length == 0);
                test(current.id.name.Equals("locate") || current.id.name.Equals("finished"));

                if(current.id.name.Equals("finished"))
                {
                    exception(current);
                }

                var co =(Test.Cookie)cookie;
                test(co.message().Equals("blahblah"));
            }

            public void deactivate(string category)
            {
                lock(this)
                {
                    test(!_deactivated);

                    _deactivated = true;
                }
            }

            private void exception(Ice.Current current)
            {
                if(current.operation.Equals("ice_ids"))
                {
                    throw new Test.TestIntfUserException();
                }
                else if(current.operation.Equals("requestFailedException"))
                {
                    throw new Ice.ObjectNotExistException();
                }
                else if(current.operation.Equals("unknownUserException"))
                {
                    var ex = new Ice.UnknownUserException();
                    ex.unknown = "reason";
                    throw ex;
                }
                else if(current.operation.Equals("unknownLocalException"))
                {
                    var ex = new Ice.UnknownLocalException();
                    ex.unknown = "reason";
                    throw ex;
                }
                else if(current.operation.Equals("unknownException"))
                {
                    var ex = new Ice.UnknownException();
                    ex.unknown = "reason";
                    throw ex;
                }
                else if(current.operation.Equals("userException"))
                {
                    throw new Test.TestIntfUserException();
                }
                else if(current.operation.Equals("localException"))
                {
                    var ex = new Ice.SocketException();
                    ex.error = 0;
                    throw ex;
                }
                else if(current.operation.Equals("csException"))
                {
                    throw new System.Exception("message");
                }
                else if(current.operation.Equals("unknownExceptionWithServantException"))
                {
                    throw new Ice.UnknownException("reason");
                }
                else if(current.operation.Equals("impossibleException"))
                {
                    throw new Test.TestIntfUserException(); // Yes, it really is meant to be TestIntfException.
                }
                else if(current.operation.Equals("intfUserException"))
                {
                    throw new Test.TestImpossibleException(); // Yes, it really is meant to be TestImpossibleException.
                }
                else if(current.operation.Equals("asyncResponse"))
                {
                    throw new Test.TestImpossibleException();
                }
                else if(current.operation.Equals("asyncException"))
                {
                    throw new Test.TestImpossibleException();
                }
            }

            private bool _deactivated;
            private string _category;
            private int _requestId;
        }
    }
}
