/*
 * Class9.cs --
 *
 * Copyright (c) 2007-2012 by Joe Mistachkin.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: $
 */

using System;
using System.Globalization;
using System.Reflection;
using Eagle._Attributes;
using Eagle._Components.Public;
using Eagle._Components.Public.Delegates;
using Eagle._Containers.Public;
using Eagle._Interfaces.Public;

namespace Sample
{
    //
    // FIXME: Always change this GUID.
    //
    [ObjectId("d8e4e05f-cd71-4cbe-9ba6-f87a653a96d2")]
    internal sealed class Class9 : IScriptBinder
    {
        #region Public Constructors
        public Class9(
            Interpreter interpreter,
            IScriptBinder parentBinder
            )
        {
            this.parentBinder = parentBinder;

            ///////////////////////////////////////////////////////////////////

            AddClass2(interpreter);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Private Methods
        private void AddClass2(
            Interpreter interpreter
            )
        {
            if (parentBinder != null)
            {
                ReturnCode code;
                Result error = null;

                code = parentBinder.AddToStringCallback(
                    typeof(Class2), FromClass2, ref error);

                if (code != ReturnCode.Ok)
                    Utility.Complain(interpreter, code, error);

                code = parentBinder.AddChangeTypeCallback(
                    typeof(Class2), ToClass2, ref error);

                if (code != ReturnCode.Ok)
                    Utility.Complain(interpreter, code, error);
            }
        }

        ///////////////////////////////////////////////////////////////////////

        private static ReturnCode FromClass2(
            Interpreter interpreter, /* NOT USED */
            Type type, /* NOT USED */
            object value,
            OptionDictionary options, /* NOT USED */
            CultureInfo cultureInfo, /* NOT USED */
            IClientData clientData, /* NOT USED */
            ref string text,
            ref Result error
            )
        {
            if (value is Class2)
            {
                text = ((Class2)value).Description;
                return ReturnCode.Ok;
            }
            else
            {
                error = "type mismatch, need Class2";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////

        private static ReturnCode ToClass2(
            Interpreter interpreter,
            Type type, /* NOT USED */
            string text,
            OptionDictionary options, /* NOT USED */
            CultureInfo cultureInfo, /* NOT USED */
            IClientData clientData, /* NOT USED */
            ref object value, /* Sample.Class2 */
            ref Result error
            )
        {
            long token = 0;
            ICommand command = null;

            if (interpreter.GetCommand(
                    text, LookupFlags.NoWrapper, ref token, ref command,
                    ref error) == ReturnCode.Ok)
            {
                value = command;
                return ReturnCode.Ok;
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IBinder Members
        public FieldInfo BindToField(
            BindingFlags bindingAttr,
            FieldInfo[] match,
            object value,
            CultureInfo culture
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.BindToField(
                bindingAttr, match, value, culture);
        }

        ///////////////////////////////////////////////////////////////////////

        public MethodBase BindToMethod(
            BindingFlags bindingAttr,
            MethodBase[] match,
            ref object[] args,
            ParameterModifier[] modifiers,
            CultureInfo culture,
            string[] names,
            out object state
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.BindToMethod(
                bindingAttr, match, ref args, modifiers, culture, names,
                out state);
        }

        ///////////////////////////////////////////////////////////////////////

        public object ChangeType(
            object value,
            Type type,
            CultureInfo culture
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.ChangeType(value, type, culture);
        }

        ///////////////////////////////////////////////////////////////////////

        public void ReorderArgumentArray(
            ref object[] args,
            object state
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            parentBinder.ReorderArgumentArray(ref args, state);
        }

        ///////////////////////////////////////////////////////////////////////

        public MethodBase SelectMethod(
            BindingFlags bindingAttr,
            MethodBase[] match,
            Type[] types,
            ParameterModifier[] modifiers
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.SelectMethod(
                bindingAttr, match, types, modifiers);
        }

        ///////////////////////////////////////////////////////////////////////

        public PropertyInfo SelectProperty(
            BindingFlags bindingAttr,
            PropertyInfo[] match,
            Type returnType,
            Type[] indexes,
            ParameterModifier[] modifiers
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.SelectProperty(
                bindingAttr, match, returnType, indexes, modifiers);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IScriptBinder Members
        public IBinder FallbackBinder
        {
            get
            {
                return (parentBinder != null) ?
                    parentBinder.FallbackBinder : null;
            }
            set
            {
                if (parentBinder != null)
                    parentBinder.FallbackBinder = value;
            }
        }

        ///////////////////////////////////////////////////////////////////////

        private IScriptBinder parentBinder;
        public IScriptBinder ParentBinder
        {
            get { return parentBinder; }
            set { parentBinder = value; }
        }

        ///////////////////////////////////////////////////////////////////////

        public bool Debug
        {
            get { return (parentBinder != null) ? parentBinder.Debug : false; }
            set { if (parentBinder != null) parentBinder.Debug = value; }
        }

        ///////////////////////////////////////////////////////////////////////

        public bool DoesMatchType(
            object value,
            Type type
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.DoesMatchType(value, type);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool IsCoreCallback(
            Delegate callback
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.IsCoreCallback(callback);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool IsCoreStringListToStringCallback(
            ToStringCallback callback
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.IsCoreStringListToStringCallback(callback);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool IsCoreStringListChangeTypeCallback(
            ChangeTypeCallback callback
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.IsCoreStringListChangeTypeCallback(callback);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool HasToStringTypes()
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.HasToStringTypes();
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode ListToStrings(
            ref TypeList types,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.ListToStrings(ref types, ref error);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool IsCoreToStringCallback(
            ToStringCallback callback
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.IsCoreToStringCallback(callback);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool HasToStringCallback(
            Type type,
            bool primitive
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.HasToStringCallback(type, primitive);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool HasToStringCallback(
            Type type,
            bool primitive,
            ref ToStringCallback callback
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.HasToStringCallback(
                type, primitive, ref callback);
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode AddToStringCallback(
            Type type,
            ToStringCallback callback,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.AddToStringCallback(type, callback, ref error);
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveToStringCallback(
            Type type,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.RemoveToStringCallback(type, ref error);
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode InvokeToStringCallback(
            ToStringCallback callback,
            Type type,
            object value,
            OptionDictionary options,
            CultureInfo cultureInfo,
            IClientData clientData,
            ref string text,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.InvokeToStringCallback(
                callback, type, value, options, cultureInfo, clientData,
                ref text, ref error);
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode ToString(
            IChangeTypeData changeTypeData,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.ToString(changeTypeData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool HasChangeTypes()
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.HasChangeTypes();
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode ListChangeTypes(
            ref TypeList types,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.ListChangeTypes(ref types, ref error);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool IsCoreChangeTypeCallback(
            ChangeTypeCallback callback
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.IsCoreChangeTypeCallback(callback);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool HasChangeTypeCallback(
            Type type,
            bool primitive
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.HasChangeTypeCallback(type, primitive);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool HasChangeTypeCallback(
            Type type,
            bool primitive,
            ref ChangeTypeCallback callback
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.HasChangeTypeCallback(
                type, primitive, ref callback);
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode AddChangeTypeCallback(
            Type type,
            ChangeTypeCallback callback,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.AddChangeTypeCallback(
                type, callback, ref error);
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveChangeTypeCallback(
            Type type,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.RemoveChangeTypeCallback(type, ref error);
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode InvokeChangeTypeCallback(
            ChangeTypeCallback callback,
            Type type,
            string text,
            OptionDictionary options,
            CultureInfo cultureInfo,
            IClientData clientData,
            ref object value,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.InvokeChangeTypeCallback(
                callback, type, text, options, cultureInfo, clientData,
                ref value, ref error);
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode ChangeType(
            IChangeTypeData changeTypeData,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.ChangeType(changeTypeData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////

        public ReturnCode SelectMethodIndex(
            Type type,
            CultureInfo cultureInfo,
            TypeList parameterTypes,
            MethodBase[] methods,
            object[] args,
            IntList methodIndexList,
            ObjectArrayList argsList,
            ref int methodIndex,
            ref Result error
            )
        {
            if (parentBinder == null)
                throw new InvalidOperationException();

            return parentBinder.SelectMethodIndex(
                type, cultureInfo, parameterTypes, methods, args,
                methodIndexList, argsList, ref methodIndex, ref error);
        }
        #endregion
    }
}
