/*
 * Test.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.IO;
using System.Reflection;
using Eagle._Attributes;
using Eagle._Components.Private;
using Eagle._Components.Public;
using Eagle._Constants;
using Eagle._Containers.Public;
using Eagle._Interfaces.Public;

namespace Eagle._Plugins
{
    [ObjectId("f5813bfc-7fae-45bb-ab05-9e2d9f1ef49f")]
    [PluginFlags(
        PluginFlags.System | PluginFlags.Command |
        PluginFlags.Static | PluginFlags.Test)]
    internal sealed class Test : Default
    {
        #region Public Constructors
        public Test(
            IPluginData pluginData
            )
            : base(pluginData)
        {
            this.Flags |= AttributeOps.GetPluginFlags(GetType().BaseType) |
                AttributeOps.GetPluginFlags(this);
        }
        #endregion

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

        #region Public Properties
        private bool enableExecute;
        public bool EnableExecute
        {
            get { return enableExecute; }
            set { enableExecute = value; }
        }

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

        private bool enableGetStream;
        public bool EnableGetStream
        {
            get { return enableGetStream; }
            set { enableGetStream = value; }
        }

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

        private bool enableGetString;
        public bool EnableGetString
        {
            get { return enableGetString; }
            set { enableGetString = value; }
        }
        #endregion

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

        #region IState Members
        public override ReturnCode Initialize(
            Interpreter interpreter,
            IClientData clientData,
            ref Result result
            )
        {
            ReturnCode code;

            if (interpreter != null)
            {
                long token = 0;

                //
                // NOTE: The test plugin command is non-standard.
                //
                if (!interpreter.IsStandard())
                {
                    //
                    // NOTE: Perform any plugin initialization steps here.
                    //
                    string name = FormatOps.PluginCommand(
                        this.Assembly, this.Name, typeof(_Commands.Nop), null);

                    code = interpreter.AddCommand(
                        new _Commands.Nop(new CommandData(
                            name, null, null, clientData, typeof(_Commands.Nop).FullName,
                            CommandFlags.None, this, 0)), null, ref token, ref result);
                }
                else
                {
                    code = ReturnCode.Ok;
                }

                Version version = (code == ReturnCode.Ok) ? this.Version : null;

                if (code == ReturnCode.Ok)
                    code = interpreter.ProvidePackage(
                        this.GetType().FullName, version, ref result);

                if (code == ReturnCode.Ok)
                {
                    if (token != 0)
                        this.CommandTokens.Add(token);

                    this.Initialized = true;

                    result = StringList.MakeList(this.Name, version);
                }
            }
            else
            {
                result = "invalid interpreter";
                code = ReturnCode.Error;
            }

            return code;
        }

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

        public override ReturnCode Terminate(
            Interpreter interpreter,
            IClientData clientData,
            ref Result result
            )
        {
            ReturnCode code;

            if (interpreter != null)
            {
                code = interpreter.RemoveCommands(
                    this, clientData, CommandFlags.None, ref result);

                Version version = (code == ReturnCode.Ok) ? this.Version : null;

                if (code == ReturnCode.Ok)
                    code = interpreter.WithdrawPackage(
                        this.GetType().FullName, version, ref result);

                if (code == ReturnCode.Ok)
                {
                    //
                    // HACK: Cleanup the test plugin token in the interpreter
                    //       state because this is the only place we can be
                    //       100% sure it will get done.
                    //
                    interpreter.InternalTestPluginToken = 0;

                    result = StringList.MakeList(this.Name, version);
                }
            }
            else
            {
                result = "invalid interpreter";
                code = ReturnCode.Error;
            }

            return code;
        }
        #endregion

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

        #region IExecuteRequest Members
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            object request,
            ref object response,
            ref Result error
            )
        {
            if (!enableExecute)
            {
                return base.Execute(
                    interpreter, clientData, request, ref response,
                    ref error);
            }

            if (clientData != null)
            {
                response = new object[] {
                    interpreter, clientData.Data, request
                };

                return ReturnCode.Ok;
            }
            else
            {
                error = "invalid clientData";
                return ReturnCode.Error;
            }
        }
        #endregion

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

        #region IPlugin Members
        public override Stream GetStream(
            Interpreter interpreter,
            string name,
            ref Result error
            )
        {
            if (!enableGetStream)
                return base.GetStream(interpreter, name, ref error);

            if (String.IsNullOrEmpty(name))
            {
                error = "invalid stream name";
                return null;
            }

            Assembly assembly = this.Assembly;

            if (assembly == null)
            {
                error = "plugin assembly not available";
                return null;
            }

            try
            {
                Stream stream = assembly.GetManifestResourceStream(name);

                if (stream != null)
                    return stream;

                stream = assembly.GetManifestResourceStream(
                    PathOps.MakeRelativePath(name, true));

                if (stream != null)
                    return stream;

                string prefix = GlobalState.GetBasePath();

                if (name.StartsWith(prefix, PathOps.ComparisonType))
                {
                    stream = assembly.GetManifestResourceStream(
                        name.Substring(prefix.Length));

                    if (stream != null)
                        return stream;
                }

                stream = assembly.GetManifestResourceStream(name);

                if (stream != null)
                    return stream;

                stream = assembly.GetManifestResourceStream(
                    Path.GetFileName(name));

                if (stream != null)
                    return stream;

                error = "stream not found";
            }
            catch (Exception e)
            {
                error = e;
            }

            return null;
        }

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

        public override string GetString(
            Interpreter interpreter,
            string name,
            CultureInfo cultureInfo,
            ref Result error
            )
        {
            if (!enableGetString)
            {
                return base.GetString(
                    interpreter, name, cultureInfo, ref error);
            }

            if (name != null)
            {
                return String.Format(
                    "interpreter: {0}, name: {1}, cultureInfo: {2}",
                    FormatOps.WrapOrNull(interpreter),
                    FormatOps.WrapOrNull(name),
                    FormatOps.WrapOrNull(cultureInfo));
            }
            else
            {
                error = "invalid string name";
                return null;
            }
        }

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

        public override ReturnCode About(
            Interpreter interpreter,
            ref Result result
            )
        {
            result = FormatOps.PluginAbout(this, false);
            return ReturnCode.Ok;
        }

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

        public override ReturnCode Options(
            Interpreter interpreter,
            ref Result result
            )
        {
            result = new StringList(DefineConstants.OptionList, false);
            return ReturnCode.Ok;
        }
        #endregion
    }
}
