/*
 * This work is licensed unde the MIT License (MIT)
 * Copyright (c) 2020-2021 (overlord)
 * https://opensource.org/licenses/MIT
 */
using System;
using System.Numerics;
using SMath.Manager;
using SMath.Math;
using SMath.Math.Numeric;

namespace BigIntegerArithmetics
{
    /// <summary>
    /// Primitives handler.
    /// </summary>
    public partial class BigIntegerArithmetics : IPluginHandleEvaluation, IPluginLowLevelEvaluation, IPluginMathNumericEvaluation
#if _DEBUG
        , IPluginLowLevelEvaluationFast
#endif
    {
        #region Private fields

        private TermInfo[] TermInfos;
        private AssemblyInfo[] AssemblyInfos;

        #endregion

        #region IPlugin implementation
 
        public void Initialize()
        {
            this.AssemblyInfos = new AssemblyInfo[]
            {
                new AssemblyInfo("SMath Studio", new Version(0, 99), new Guid("18d185eb-489a-4ef8-aa35-b7ca658543cc"))
            };

            this.TermInfos = new TermInfo[]
            {
                SMathFunctions.bigAbs.GetTermInfo(),
                SMathFunctions.bigAdd.GetTermInfo(),
                SMathFunctions.bigCmp.GetTermInfo(),
                SMathFunctions.bigDiv.GetTermInfo(),
                SMathFunctions.bigGCD.GetTermInfo(),
                SMathFunctions.bigLog.GetTermInfo(),
                SMathFunctions.bigLog10.GetTermInfo(),
                SMathFunctions.bigMax.GetTermInfo(),
                SMathFunctions.bigMin.GetTermInfo(),
                SMathFunctions.bigMod.GetTermInfo(),
                SMathFunctions.bigModPow.GetTermInfo(),
                SMathFunctions.bigMul.GetTermInfo(),
                SMathFunctions.bigNeg.GetTermInfo(),
                SMathFunctions.bigPow.GetTermInfo(),
                SMathFunctions.bigSub.GetTermInfo(),
            };
        }

        public AssemblyInfo[] Dependences
        {
            get { return this.AssemblyInfos; }
        }

        #endregion

        #region IPluginHandleEvaluation implementation
 
        public TermInfo[] GetTermsHandled(SessionProfile sessionProfile)
        {
            return this.TermInfos;
        }

        #endregion

        #region IDisposable implementation

        public void Dispose()
        {
            // Do nothing
        }

        #endregion

        public bool ExpressionEvaluation(Term root, Term[][] args, ref Store context, ref Term[] result)
        {
            if (root.Type != TermType.Function)
                return false;
            if (SMathFunctions.bigAbs.IsSupport(root))
                return SMathFunctions.bigAbs.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigAdd.IsSupport(root))
                return SMathFunctions.bigAdd.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigCmp.IsSupport(root))
                return SMathFunctions.bigCmp.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigDiv.IsSupport(root))
                return SMathFunctions.bigDiv.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigGCD.IsSupport(root))
                return SMathFunctions.bigGCD.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigLog.IsSupport(root))
                return SMathFunctions.bigLog.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigLog10.IsSupport(root))
                return SMathFunctions.bigLog10.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigMax.IsSupport(root))
                return SMathFunctions.bigMax.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigMin.IsSupport(root))
                return SMathFunctions.bigMin.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigMod.IsSupport(root))
                return SMathFunctions.bigMod.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigModPow.IsSupport(root))
                return SMathFunctions.bigModPow.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigMul.IsSupport(root))
                return SMathFunctions.bigMul.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigNeg.IsSupport(root))
                return SMathFunctions.bigNeg.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigPow.IsSupport(root))
                return SMathFunctions.bigPow.ExpressionEvaluation(root, args, ref context, ref result);
            if (SMathFunctions.bigSub.IsSupport(root))
                return SMathFunctions.bigSub.ExpressionEvaluation(root, args, ref context, ref result);
            return false;
        }

        public bool NumericEvaluation(Term value, TNumber[] args, ref TNumber result)
        {
            throw new NotImplementedException();
        }
    }
}