using System;
using System.IO;
using System.Windows.Forms;
using ExcelDna.Integration;


namespace Excel2Ox
{
    public class MyAddIn : IExcelAddIn
    {
        public void AutoOpen()
        {
            Excel2Ox.Init();
        }

        public void AutoClose()
        {
            //MessageBox.Show("Now in AutoClose.");
        }
    }
    public class Excel2Ox
    {
        static string m_sXllPath;       // path of this XLL
        static string m_sOxFileName;    // name of Ox code derived from XLL path and name

        public static void Init()
        {
            if (m_sOxFileName == null || m_sOxFileName.Length == 0)
            {
                m_sOxFileName = (string)XlCall.Excel(XlCall.xlGetName);
                m_sXllPath = m_sOxFileName.Substring(0, m_sOxFileName.LastIndexOf('\\'));
#if DEBUG
			    m_sOxFileName = m_sOxFileName.Replace("\\Ox_UDF\\Excel2Ox\\bin\\Debug", "");
#endif				
                if (m_sOxFileName.IndexOf('.') > 0)
                    m_sOxFileName = m_sOxFileName.Substring(0, m_sOxFileName.IndexOf('.'));
                if (m_sOxFileName.IndexOf('-') > 0)
                    m_sOxFileName = m_sOxFileName.Substring(0, m_sOxFileName.IndexOf('-'));
            }
        }
        private static string OxFuncName(string sFunc, out string sOxFile)
        {
            int idx = sFunc.IndexOf('?');
  
            if (idx >= 0)
            {
                sOxFile = sFunc.Substring(0, idx);
                if (sOxFile.IndexOfAny(new char[] { '\\', '/' }) < 0)
                {
                    sOxFile = m_sXllPath + "\\" + sOxFile;
                }
                return sFunc.Substring(idx + 1);
            }
            else
            {
                sOxFile = m_sOxFileName;
                return sFunc;
            }
        }

        [ExcelFunction(Description = "Calls an Ox function with one argument")]
        public static object OxFunc1([ExcelArgument(Description = "Ox Function name")]string sFunc, [ExcelArgument(Description = "Argument (optional)")]object[,] arg)
        {
            // the following doesn't work: cannot call xlcAlert from a function, or any xlc* macros, only xlf* functions.
            // XlCall.Excel(XlCall.xlcAlert, "Test");
            // But they can call macros from xlAuto* functions.

            string soxfile;
            sFunc = OxFuncName(sFunc, out soxfile);
 
            if (sFunc.Length == 0)
                return "#Ox error: Ox function name missing";
            if (ExcelDnaUtil.IsInFunctionWizard())
                return "#Ox ready";

            object ret_val = "#OxError";
            string output;
            var originalConsoleOut = Console.Out; // preserve the original stream
            try
            {
                using (var writer = new StringWriter())
                {
                    Console.SetOut(writer);
                    ret_val = OxCallBack.OxCall(soxfile, sFunc, arg);
                    writer.Flush();
                    output = writer.GetStringBuilder().ToString();
                }
            }
            catch
            {
            }
            if (OxCallBack.HaveErrorMessage())
                MessageBox.Show(OxCallBack.GetErrorMessage());
            return ret_val;
        }
        [ExcelFunction(Description = "Calls an Ox function specifying argument count")]
        public static object OxFuncc([ExcelArgument(Description = "Ox Function name")]string sFunc, 
            [ExcelArgument(Description = "Argument count")]int cArgs, object[,] arg1, object[,] arg2, object[,] arg3, object[,] arg4, 
            object[,] arg5, object[,] arg6, object[,] arg7, object[,] arg8, object[,] arg9, object[,] arg10, object[,] arg11, object[,] arg12,
            object[,] arg13, object[,] arg14, object[,] arg15, object[,] arg16)
        {
            string soxfile;
            sFunc = OxFuncName(sFunc, out soxfile);
            if (sFunc.Length == 0)
                return "#Ox error: Ox function name missing";
            if (OxCallBack.CountArgs(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16) != cArgs)
                return "#Ox error: arguments missing";
            if (ExcelDnaUtil.IsInFunctionWizard())
                return "#Ox ready";

            object ret_val = "#OxError";
            string output;
            var originalConsoleOut = Console.Out; // preserve the original stream
            try
            {
                using (var writer = new StringWriter())
                {
                    Console.SetOut(writer);
                    ret_val = OxCallBack.OxCall(soxfile, sFunc, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16);
                    writer.Flush();
                    output = writer.GetStringBuilder().ToString();
                }
            }
            catch
            {
            }
            if (OxCallBack.HaveErrorMessage())
                MessageBox.Show(OxCallBack.GetErrorMessage());
            return ret_val;
        }
    }
}
