using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.CodeDom;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.IO;

namespace DynamicCompiler
{
    public class CodeBuilder
    {
        StringCollection importNameSpace;
        List<FunctionScript> functionScriptList;
        string typeNamespace;
        string className;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="importNameSpace">导入命名空间</param>
        /// <param name="className">类名</param>
        /// <param name="functionInfoList">函数列表</param>
        public CodeBuilder(StringCollection importNameSpace,string typeNamespace,string className,
            List<FunctionScript> functionScriptList)
        {
            if (functionScriptList == null || functionScriptList.Count==0)
            {
                throw new Exception("函数列表不能为空");
            }
            this.importNameSpace = importNameSpace;
            this.typeNamespace = typeNamespace;
            this.className = className;
            this.functionScriptList = functionScriptList;
            if (functionScriptList.GroupBy(c => c.ClassName).Count() > 1)
            {
                throw new Exception("这些函数不属于一个类");
            }

        }
        public CodeBuilder(string typeNamespace,string className,
            List<FunctionScript> functionScriptList):this( null,typeNamespace,className,functionScriptList)
        {

        }
        public CodeBuilder(List<FunctionScript> functionScriptList):
            this(functionScriptList.Count==0?null:functionScriptList[0].ClassNameSpace,
            functionScriptList.Count == 0 ? null : functionScriptList[0].ClassName,
            functionScriptList)
        {
        }
        private  CodeCompileUnit CreateExecutionClass()
        {
            // 创建CodeCompileUnit以包含代码
            CodeCompileUnit ccu = new CodeCompileUnit(); // 分配需要的命名空间 
            CodeNamespace cns = new CodeNamespace(typeNamespace);
            cns.Imports.Add(new CodeNamespaceImport("System"));
            ccu.Namespaces.Add(cns); // 创建新的类声明
            CodeTypeDeclaration codeClass = new CodeTypeDeclaration(className);
            cns.Types.Add(codeClass); // 在命名空间下加入类
            foreach (var functionScript in functionScriptList)
            {
                CodeMemberMethod method = new CodeMemberMethod();
                method.Name = functionScript.FunctionName;
                //方法的访问标识符为public static
                method.Attributes = MemberAttributes.Static | MemberAttributes.Public;
                foreach (var parameter in functionScript.GetParameterList())
                {
                    method.Parameters.Add(parameter);
                }

                if (functionScript.ReturnType != null)
                {
                    method.ReturnType = new CodeTypeReference(Type.GetType(functionScript.ReturnType)); 
  
                }
                // 添加方法实体需要的代码
                CodeSnippetStatement methodBody = new CodeSnippetStatement(functionScript.ScriptBody);
                method.Statements.Add(methodBody);

                codeClass.Members.Add(method); 

            }
            return ccu;
        }
        public  string GenerateCode()
        {
            // 调用我们前面的方法创建CodeCompileUnit
            CodeCompileUnit ccu = CreateExecutionClass();
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CodeGeneratorOptions options = new CodeGeneratorOptions();
            options.BlankLinesBetweenMembers = false;
            options.BracingStyle = "C";//大括号换行
            options.IndentString = "\t";
            StringWriter sw = new StringWriter();
            try
            {
                provider.GenerateCodeFromCompileUnit(ccu, sw, options);
                sw.Flush();
            }
            finally
            {
                sw.Close();
            }
            return sw.GetStringBuilder().ToString();
        }
    }
}
