using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Hosting;
using System.Web.Script.Serialization;
using Helpers.Log;
using Helpers.Common;
using IHDMTDataSource;
using Ionic.Zip;
using log4net;
//test comment
public class DMT : IDMT
{
    #region Properties & Fields

    #region Fields

    private ILog logger = Helpers.Log.Logger.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.Name);
    private JavaScriptSerializer jsSerializer;

    #endregion

    #region Static Properties

    private const string DMT_API_DIR_PATH = @"app\custom-screens\dmt\api\";
    private const string DMT_API_DLL_FILE_NAME = "IHDMTApi.dll";

    //private static Dictionary<string, Process> Debuggers;

    #endregion

    #endregion

    //static DMT()
    //{
    //    Debuggers = new Dictionary<string, Process>();
    //}

    public DMT()
    {
        this.jsSerializer = new JavaScriptSerializer
        {
            MaxJsonLength = 2147483647,
        };
    }

    #region Methods

    private byte[] BuildScriptPackage(string fromDirPath)
    {
        //string fromDirPath = Path.Combine(Path.GetDirectoryName(this.Request.PhysicalPath), "temp");

        string zipFilePath = Path.Combine(fromDirPath, "program.zip");

        //Delete dmt api file to create zip file with all the files in the temp folder.
        //Since dmt api file was necessary only for compilation, it is not needed anymore.
        File.Delete(Path.Combine(fromDirPath, DMT_API_DLL_FILE_NAME));

        //Build zip file.
        using (ZipFile zip = new ZipFile())
        {
            //Set dummy password. Do not need to much security for now.
            zip.Password = "123456";

            //Add files
            string[] files = Directory.GetFiles(fromDirPath);

            foreach (string file in files)
                zip.AddFile(file, "");


            //Add subdirs
            string[] subDirs = Directory.GetDirectories(fromDirPath);

            foreach (string dir in subDirs)
                zip.AddDirectory(dir, "");


            //Write zip file to disk
            zip.Save(zipFilePath);
        }

        this.logger.DebugFormat("Zip path {0}.", zipFilePath);

        //Return zip file binary data
        return File.ReadAllBytes(zipFilePath);
    }
    private byte[] BuildProjectPackage(string fromDirPath)
    {
        string zipFilePath = Path.Combine(fromDirPath, "project.zip");

        //Build zip file.
        using (ZipFile zip = new ZipFile())
        {
            zip.AddDirectory(fromDirPath, "");

            //Write zip file to disk
            zip.Save(zipFilePath);
        }

        this.logger.DebugFormat("Zip path {0}.", zipFilePath);

        //Return zip file binary data
        return File.ReadAllBytes(zipFilePath);
    }
    private Helpers.Common.Response BuildSource(int sourceId, string code, string outputName, string outputDirPath, bool includeOnlyReferenceFiles)
    {
        Helpers.Common.Response response;

        //Create output folder
        if (Directory.Exists(outputDirPath) == false)
            Directory.CreateDirectory(outputDirPath);


        this.FetchScriptDependencies(sourceId, outputDirPath, includeOnlyReferenceFiles);


        var compResults = this.CompileSource(code, outputName, outputDirPath);

        if (compResults.Errors.Count == 0)
        {
            response = new Helpers.Common.Response();
        }
        else
        {
            List<string> errorsMsg = new List<string>();

            foreach (CompilerError error in compResults.Errors)
            {
                if (error.IsWarning == false)
                {
                    errorsMsg.Add(string.Format(
                        "[Text: \"{0}\", Number: {1}, Line: {2}, Column: {3}]",
                        error.ErrorText,
                        error.ErrorNumber,
                        error.Line,
                        error.Column
                    ));
                }
            }

            this.logger.WarnFormat("Failed to compile. Errors: [{0}].", string.Join(", ", errorsMsg));

            response = new Helpers.Common.Response(string.Format("DMT_FAILED_COMPILATION|{0}", string.Join(", ", errorsMsg)));
        }

        return response;
    }
    private void ClearDirectory(string path)
    {
        string[] files = Directory.GetFiles(path);
        string[] dirs = Directory.GetDirectories(path);

        foreach (string file in files)
        {
            File.SetAttributes(file, FileAttributes.Normal);
            File.Delete(file);
        }

        foreach (string dir in dirs)
        {
            this.ClearDirectory(dir);

            Directory.Delete(dir);
        }
    }
    private CompilerResults CompileSource(string code, string name, string outputDirPath/*, bool debug = false*/)
    {
        string apiDirPath = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, DMT_API_DIR_PATH, "project-template", "_Internal", "dll");
        //string outputDirPath;

        //outputDirPath = (debug == false)
        //                    ? Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetTempFileName()))
        //                    : Path.Combine(apiDirPath, "debug");

        //this.logger.DebugFormat("Output folder: {0}.", outputDirPath);


        ////Create output folder if does not exist.
        ////If exists, delete all its content.
        //if (Directory.Exists(outputDirPath) == false)
        //    Directory.CreateDirectory(outputDirPath);

        //Configure compilation.
        CodeDomProvider c = CodeDomProvider.CreateProvider("CSharp");

        CompilerParameters cp = new CompilerParameters
        {
            GenerateInMemory = false,
        };

        //if (debug == false)
        //{

	this.logger.DebugFormat("Name+++: {0}, Path++++: {1}", name, outputDirPath);
        string outputFilePath = Path.Combine(outputDirPath, name + ".dll");

        this.logger.DebugFormat("Output file: {0}.", outputFilePath);

        cp.CompilerOptions = "/t:library";
        cp.OutputAssembly = outputFilePath;
        //}
        //else
        //{
        //    cp.GenerateExecutable = true;
        //}


        cp.ReferencedAssemblies.AddRange(new string[] {
            #region .Net assemblies

            @"Microsoft.VisualBasic.Compatibility.dll",
            @"Microsoft.VisualBasic.dll",
            @"Microsoft.VisualC.dll",
            @"Microsoft.VisualC.STLCLR.dll",
            //@"mscorlib.dll",
            //@"PresentationBuildTasks.dll",
            //@"PresentationCore.dll",
            //@"PresentationFramework.Aero.dll",
            //@"PresentationFramework.Classic.dll",
            //@"PresentationFramework.dll",
            //@"PresentationFramework.Luna.dll",
            //@"PresentationFramework.Royale.dll",
            //@"ReachFramework.dll",
            @"sysglobl.dll",
            @"System.Activities.Core.Presentation.dll",
            @"System.Activities.dll",
            @"System.Activities.DurableInstancing.dll",
            @"System.Activities.Presentation.dll",
            @"System.AddIn.Contract.dll",
            @"System.AddIn.dll",
            @"System.ComponentModel.Composition.dll",
            @"System.ComponentModel.DataAnnotations.dll",
            @"System.configuration.dll",
            @"System.Configuration.Install.dll",
            @"System.Core.dll",
            @"System.Data.DataSetExtensions.dll",
            @"System.Data.dll",
            @"System.Data.Entity.Design.dll",
            @"System.Data.Entity.dll",
            @"System.Data.Linq.dll",
            @"System.Data.OracleClient.dll",
            @"System.Data.Services.Client.dll",
            @"System.Data.Services.Design.dll",
            @"System.Data.Services.dll",
            @"System.Data.SqlXml.dll",
            @"System.Deployment.dll",
            @"System.Design.dll",
            @"System.Device.dll",
            @"System.DirectoryServices.AccountManagement.dll",
            @"System.DirectoryServices.dll",
            @"System.DirectoryServices.Protocols.dll",
            @"System.dll",
            @"System.Drawing.Design.dll",
            @"System.Drawing.dll",
            @"System.EnterpriseServices.dll",
            //@"System.EnterpriseServices.Thunk.dll",
            //@"System.EnterpriseServices.Wrapper.dll",
            @"System.IdentityModel.dll",
            @"System.IdentityModel.Selectors.dll",
            @"System.IO.Log.dll",
            @"System.Management.dll",
            @"System.Management.Instrumentation.dll",
            @"System.Messaging.dll",
            @"System.Net.dll",
            @"System.Numerics.dll",
            //@"System.Printing.dll",
            @"System.Runtime.Caching.dll",
            @"System.Runtime.DurableInstancing.dll",
            @"System.Runtime.Remoting.dll",
            @"System.Runtime.Serialization.dll",
            @"System.Runtime.Serialization.Formatters.Soap.dll",
            @"System.Security.dll",
            @"System.ServiceModel.Activation.dll",
            @"System.ServiceModel.Activities.dll",
            @"System.ServiceModel.Channels.dll",
            @"System.ServiceModel.Discovery.dll",
            @"System.ServiceModel.dll",
            @"System.ServiceModel.Routing.dll",
            @"System.ServiceModel.Web.dll",
            @"System.ServiceProcess.dll",
            //@"System.Speech.dll",
            @"System.Transactions.dll",
            @"System.Web.Abstractions.dll",
            @"System.Web.ApplicationServices.dll",
            @"System.Web.DataVisualization.Design.dll",
            @"System.Web.DataVisualization.dll",
            @"System.Web.dll",
            @"System.Web.DynamicData.Design.dll",
            @"System.Web.DynamicData.dll",
            @"System.Web.Entity.Design.dll",
            @"System.Web.Entity.dll",
            @"System.Web.Extensions.Design.dll",
            @"System.Web.Extensions.dll",
            @"System.Web.Mobile.dll",
            @"System.Web.RegularExpressions.dll",
            @"System.Web.Routing.dll",
            @"System.Web.Services.dll",
            @"System.Windows.Forms.DataVisualization.Design.dll",
            @"System.Windows.Forms.DataVisualization.dll",
            @"System.Windows.Forms.dll",
            //@"System.Windows.Input.Manipulations.dll",
            //@"System.Windows.Presentation.dll",
            @"System.Workflow.Activities.dll",
            @"System.Workflow.ComponentModel.dll",
            @"System.Workflow.Runtime.dll",
            @"System.WorkflowServices.dll",
            @"System.Xaml.dll",
            @"System.XML.dll",
            @"System.Xml.Linq.dll",
            //@"UIAutomationClient.dll",
            //@"UIAutomationClientsideProviders.dll",
            //@"UIAutomationProvider.dll",
            //@"UIAutomationTypes.dll",
            //@"WindowsBase.dll",
            //@"WindowsFormsIntegration.dll",
            @"XamlBuildTask.dll",
            @"Accessibility.dll",
            @"CustomMarshalers.dll",
            @"ISymWrapper.dll",
            @"Microsoft.Build.Conversion.v4.0.dll",
            @"Microsoft.Build.dll",
            @"Microsoft.Build.Engine.dll",
            @"Microsoft.Build.Framework.dll",
            @"Microsoft.Build.Tasks.v4.0.dll",
            @"Microsoft.Build.Utilities.v4.0.dll",
            @"Microsoft.CSharp.dll",
            @"Microsoft.JScript.dll",
            @"Microsoft.VisualBasic.Compatibility.Data.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.VisualBasic.Compatibility.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.VisualBasic.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.VisualC.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.VisualC.STLCLR.dll",
            ////@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationBuildTasks.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationCore.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationFramework.Aero.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationFramework.Classic.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationFramework.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationFramework.Luna.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\PresentationFramework.Royale.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\ReachFramework.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\sysglobl.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Activities.Core.Presentation.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Activities.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Activities.DurableInstancing.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Activities.Presentation.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.AddIn.Contract.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.AddIn.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ComponentModel.Composition.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ComponentModel.DataAnnotations.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.configuration.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Configuration.Install.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.DataSetExtensions.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Entity.Design.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Entity.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Linq.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.OracleClient.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Services.Client.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Services.Design.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Services.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.SqlXml.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Deployment.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Design.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Device.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.DirectoryServices.AccountManagement.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.DirectoryServices.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.DirectoryServices.Protocols.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Drawing.Design.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Drawing.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.EnterpriseServices.dll",
            ////@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.EnterpriseServices.Thunk.dll",
            ////@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.EnterpriseServices.Wrapper.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.IdentityModel.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.IdentityModel.Selectors.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.IO.Log.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Management.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Management.Instrumentation.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Messaging.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Net.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Numerics.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Printing.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Runtime.Caching.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Runtime.DurableInstancing.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Runtime.Remoting.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Runtime.Serialization.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Runtime.Serialization.Formatters.Soap.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Security.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.Activation.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.Activities.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.Channels.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.Discovery.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.Routing.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceModel.Web.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ServiceProcess.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Speech.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Transactions.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Abstractions.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.ApplicationServices.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.DataVisualization.Design.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.DataVisualization.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.DynamicData.Design.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.DynamicData.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Entity.Design.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Entity.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Extensions.Design.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Extensions.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Mobile.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.RegularExpressions.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Routing.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Services.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Windows.Forms.DataVisualization.Design.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Windows.Forms.DataVisualization.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Windows.Forms.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Windows.Input.Manipulations.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Windows.Presentation.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Workflow.Activities.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Workflow.ComponentModel.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Workflow.Runtime.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.WorkflowServices.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Xaml.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.XML.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Xml.Linq.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\UIAutomationClient.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\UIAutomationClientsideProviders.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\UIAutomationProvider.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\UIAutomationTypes.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\WindowsBase.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\WindowsFormsIntegration.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\XamlBuildTask.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Accessibility.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\CustomMarshalers.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\ISymWrapper.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.Build.Conversion.v4.0.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.Build.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.Build.Engine.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.Build.Framework.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.Build.Tasks.v4.0.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.Build.Utilities.v4.0.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.CSharp.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.JScript.dll",
            //@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.VisualBasic.Compatibility.Data.dll",

            #endregion
        });

        //Add assemblies from assets.
        cp.ReferencedAssemblies.AddRange(Directory.GetFiles(outputDirPath, "*.dll"));

        //Add dmt api assembly.
        cp.ReferencedAssemblies.Add(Path.Combine(apiDirPath, DMT_API_DLL_FILE_NAME));

        ////#if DEBUG
        ////            cp.IncludeDebugInformation = true;
        ////#endif


        return c.CompileAssemblyFromSource(cp, code);
    }
    //private void DebugScript()
    //{
        //    {
        //        string code = Request.Form["code"];
        //        string id = Request.Form["id"];

        //        if (string.IsNullOrWhiteSpace(id)//Means that it is starting to debug.

        //        var compResults = this.Compile(code, , true);

        //        if (compResults.Errors.Count == 0)
        //        {
        //            string apiDirPath = Path.GetDirectoryName(this.Request.PhysicalPath);
        //            string outputDirPath;
        //            string exeFilePath;

        //            outputDirPath = Path.Combine(apiDirPath, "debug");

        //            exeFilePath = Path.Combine(outputDirPath, name + ".exe");

        //            this.logger.DebugFormat("Output path: {0}.", exeFilePath);


        //            Process process = null;
        //            NDebugger debugger = new NDebugger();

        //            debugger.Options = new Options();
        //            debugger.Options.EnableJustMyCode = true;
        //            debugger.Options.SuppressJITOptimization = true;
        //            debugger.Options.StepOverDebuggerAttributes = true;
        //            debugger.Options.StepOverAllProperties = false;
        //            debugger.Options.StepOverFieldAccessProperties = true;
        //            debugger.Options.SymbolsSearchPaths = new string[0];
        //            debugger.Options.PauseOnHandledExceptions = false;

        //            process = debugger.Start(
        //                exeFilePath,
        //                Path.GetDirectoryName(exeFilePath),
        //                "",
        //                false
        //            );

        //            process.Paused += this.Process_Paused;

        //            response = new Response
        //            {
        //                Success = true,
        //                Message = string.Format("Code length: {0}, Id: {1}.", code.Length, id),
        //            };
        //        }
        //        else
        //        {
        //            List<string> errorsMsg = new List<string>();

        //            foreach (CompilerError error in compResults.Errors)
        //            {
        //                if (error.IsWarning == false)
        //                {
        //                    errorsMsg.Add(string.Format(
        //                        "[Text: \"{0}\", Number: {1}, Line: {2}, Column: {3}]",
        //                        error.ErrorText,
        //                        error.ErrorNumber,
        //                        error.Line,
        //                        error.Column
        //                    ));
        //                }
        //            }

        //            this.logger.WarnFormat("Failed to compile. Errors: [{0}].", string.Join(", ", errorsMsg));

        //            response = new Response
        //            {
        //                Success = true,
        //                Message = string.Format("Failed to compile. Errors: [{0}].", string.Join(", ", errorsMsg)),
        //            };
        //        }
        //    }
    //}
    private void DeepCopyFolder(string sourceDirPath, string targetDirPath)
    {
        foreach (string sourceSubDirPath in Directory.GetDirectories(sourceDirPath, "*", SearchOption.TopDirectoryOnly))
        {
            string targetSubDirPath = sourceSubDirPath.Replace(sourceDirPath, targetDirPath);

            Directory.CreateDirectory(targetSubDirPath);

            this.DeepCopyFolder(sourceSubDirPath, targetSubDirPath);
        }

        //Copy all the files & Replaces any files with the same name
        foreach (string newPath in Directory.GetFiles(sourceDirPath, "*.*", SearchOption.TopDirectoryOnly))
            File.Copy(newPath, newPath.Replace(sourceDirPath, targetDirPath), true);
    }
    private void FetchScriptDependencies(int sourceId, string outputDirPath, bool includeOnlyReferenceFiles)
    {
        using (SqlConnection con = new SqlConnection(WebApp.GetSystemConnectionString()))
        {
            con.Open();

            using (SqlCommand comm = new SqlCommand("IH_100020.WEB.GetDmtSourceFiles", con))
            {
                comm.CommandType = CommandType.StoredProcedure;
                comm.CommandTimeout = 300;

                comm.Parameters.Add(new SqlParameter("@sourceId", SqlDbType.Int)).Value = sourceId;
                comm.Parameters.Add(new SqlParameter("@includeOnlyReferences", SqlDbType.Bit)).Value = includeOnlyReferenceFiles;
                

                logger.DebugFormat("Calling procedure {0} ...", comm.CommandText);

                using (var dr = comm.ExecuteReader())
                {
                    while (dr.Read() == true)
                    {
                        //Save file to disk
                        File.WriteAllBytes(
                            Path.Combine(outputDirPath, dr["Name"].ToString()),
                            (byte[])dr["Content"]
                        );
                    }
                }

                //DALSecurity.CallSecuredProcedure(con, comm);
            }
        }



    }
    private Tuple<int, string, string, string> FetchScriptSource(int id)
    {
        Tuple<int, string, string, string> source = null;

        using (SqlConnection con = new SqlConnection(WebApp.GetSystemConnectionString()))
        {
            con.Open();

            using (SqlCommand comm = new SqlCommand("IH_100020.WEB.GetScriptSources", con))
            {
                comm.CommandType = CommandType.StoredProcedure;

                comm.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = id;

                logger.DebugFormat("Calling procedure {0} ...", comm.CommandText);

                using (var dr = comm.ExecuteReader())
                {
                    while (dr.Read() == true)
                    {
                        //Id	ScriptId	Name	Code	StatusCode	LastModificationTimestamp	LastModificationUser	ScriptId	ScriptName
                        //101	1102	Test02	using IHDMTDataSource; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DMT {   //Template for build an script.   //Requirements:   //+ Code should be inside class DMT.Script.Execute method. This method must be implemented.   //+ Class DMT.Script must have a public constructor with no parameters.   public class Script : UserScript { public Script() { } public override void Execute() { // //TODO: Add your script code here. // this.Api4i.Debug("testing get logs1"); } } } 	NONE	2017-11-01 20:19:46.927	NULL	1102	Test02

                        //sources.Add(new {
                        //    Name = dr["Name"].ToString(),
                        //    Code = dr["Code"].ToString(),
                        //});                         

                        source = new Tuple<int, string, string, string>(Convert.ToInt32(dr["Id"]), dr["ScriptName"].ToString(), dr["Name"].ToString(), dr["Code"].ToString());
                    }
                }

                //DALSecurity.CallSecuredProcedure(con, comm);
            }
        }

        return source;
    }

    #region Wcf Methods

    public Stream DownloadSource(Stream parameters)
    {
        Helpers.Common.Response response = null;
        TransactionLogger tranLog = null;

        try
        {
            //Deserialize parameters
            StreamReader sr = new StreamReader(parameters);
            var paramsData = this.jsSerializer.Deserialize<SourceParameters>(sr.ReadToEnd());
            sr.Dispose();


            //Initialize log stuff.
            tranLog = new TransactionLogger(this.logger, MethodBase.GetCurrentMethod().Name);

            tranLog.ParametersCollection = new Dictionary<string, object>
            {
                { "Id", paramsData.Id },
            };


            //Log transaction begin
            tranLog.LogBegin();


            string outputDirPath = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetTempFileName()));
            string templateDirPath = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, DMT_API_DIR_PATH, "project-template");
            byte[] package;

            string dependencieOutputDirPath = Path.Combine(outputDirPath, "files");


            //Create output folder
            if (Directory.Exists(outputDirPath) == false)
                Directory.CreateDirectory(outputDirPath);


            //Copy project template to output folder
            this.DeepCopyFolder(templateDirPath, outputDirPath);


            var source = this.FetchScriptSource(paramsData.Id.Value);

            int sourceId = source.Item1;
            string name = source.Item2;
            string sourceName = source.Item3;
            string code = source.Item4;


            this.FetchScriptDependencies(sourceId, dependencieOutputDirPath, false);


            File.WriteAllText(Path.Combine(outputDirPath, "Script.cs"), code);


            List<string> filesContentItems = new List<string>();
            List<string> dllsReferenceItems = new List<string>();
            string projectFileText = File.ReadAllText(Path.Combine(outputDirPath, "Api4iProjectTemplate.csproj"));

            foreach (string filePath in Directory.GetFiles(dependencieOutputDirPath))
            {
                string fileName = Path.GetFileName(filePath);

                if (fileName.EndsWith(".dll") == true)
                {
                    //For dll files, add them to project's references.
                    dllsReferenceItems.Add(string.Format(
                        @"<Reference Include=""{0}"">
                            <SpecificVersion>False</SpecificVersion>
                            <HintPath>files\{1}</HintPath>
                        </Reference>",
                        AssemblyName.GetAssemblyName(filePath).FullName,
                        fileName
                    ));

                    filesContentItems.Add(string.Format(
                        @"<Content Include=""files\{0}"" />",
                        fileName
                    ));
                }
                else
                {
                    //For common files, configure project to copy them on build to output directory.
                    filesContentItems.Add(string.Format(
                        @"<Content Include=""files\{0}"">
                            <CopyToOutputDirectory>Always</CopyToOutputDirectory>
                        </Content>",
                        fileName
                    ));
                }
            }

            projectFileText = projectFileText
                .Replace("{{CustomReferences_ReferenceItems}}", string.Join("\n    ", dllsReferenceItems))
                .Replace("{{CustomReferences_ContentItems}}", string.Join("\n    ", filesContentItems))
                .Replace("{{ScriptName}}", name);

            File.Delete(Path.Combine(outputDirPath, "Api4iProjectTemplate.csproj"));

            File.WriteAllText(Path.Combine(outputDirPath, string.Format("{0}.csproj", name)), projectFileText);



            string solutionFileText = File.ReadAllText(Path.Combine(outputDirPath, "Api4iProjectTemplate.sln"));

            solutionFileText = solutionFileText.Replace("{{ScriptName}}", name);

            File.Delete(Path.Combine(outputDirPath, "Api4iProjectTemplate.sln"));

            File.WriteAllText(Path.Combine(outputDirPath, string.Format("{0}.sln", name)), solutionFileText);



            package = this.BuildProjectPackage(outputDirPath);


            //Delete temp folder created for compilation output.
            this.ClearDirectory(outputDirPath);

            Directory.Delete(outputDirPath);


            //Set success response.
            response = new Helpers.Common.Response(
                new {
                    Content = package,
                    FileName = string.Format("{0}-{1}.zip", name, sourceName),
                }
            );


            //Log transaction end
            tranLog.LogEnd(response);
        }
        catch (Exception ex)
        {
            response = new SqlResponse(ex).ToResponse();

            if (tranLog != null)
            {
                //Log transaction end with error
                tranLog.LogEnd(ex);
            }
            else
            {
                this.logger.Error(ex);
            }
        }

        return new MemoryStream(Encoding.UTF8.GetBytes(this.jsSerializer.Serialize(response)));
    }
    public Stream RemoveScript(Stream parameters)
    {
        Helpers.Common.Response response = null;
        TransactionLogger tranLog = null;

        try
        {
            //Deserialize parameters
            StreamReader sr = new StreamReader(parameters);
            var paramsData = this.jsSerializer.Deserialize<ScriptParameters>(sr.ReadToEnd());
            sr.Dispose();


            //Initialize log stuff.
            tranLog = new TransactionLogger(this.logger, MethodBase.GetCurrentMethod().Name);

            tranLog.ParametersCollection = new Dictionary<string, object>
            {
                { "Id", paramsData.Id },
            };


            //Log transaction begin
            tranLog.LogBegin();


            using (SqlConnection con = new SqlConnection(WebApp.GetSystemConnectionString()))
            {
                con.Open();

                using (SqlCommand comm = new SqlCommand("IH_100020.WEB.RemoveScript", con))
                {
                    comm.CommandType = CommandType.StoredProcedure;
                    comm.CommandTimeout = 300;

                    comm.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = paramsData.Id;
                    comm.Parameters.Add(new SqlParameter("@currentUser", SqlDbType.VarChar)).Value = WebApp.GetUserName();

                    logger.DebugFormat("Calling procedure {0} ...", comm.CommandText);

                    comm.ExecuteNonQuery();

                    //DALSecurity.CallSecuredProcedure(con, comm);
                }
            }


            //Set success response
            response = new Helpers.Common.Response();


            //Log transaction end
            tranLog.LogEnd(response);
        }
        catch (Exception ex)
        {
            if (response == null)
                response = new SqlResponse(ex).ToResponse();

            if (tranLog != null)
            {
                //Log transaction end with error
                tranLog.LogEnd(ex);
            }
            else
            {
                this.logger.Error(ex);
            }
        }

        return new MemoryStream(Encoding.UTF8.GetBytes(this.jsSerializer.Serialize(response)));
    }
    public Stream RemoveSourceFiles(Stream parameters)
    {
        Helpers.Common.Response response = null;
        TransactionLogger tranLog = null;

        try
        {
            //Deserialize parameters
            StreamReader sr = new StreamReader(parameters);
            var paramsData = this.jsSerializer.Deserialize<SourceFilesParameters>(sr.ReadToEnd());
            sr.Dispose();


            //Initialize log stuff.
            tranLog = new TransactionLogger(this.logger, MethodBase.GetCurrentMethod().Name);

            tranLog.ParametersCollection = new Dictionary<string, object>
            {
                { "Id", paramsData.Id },
                { "Files", string.Format("[{0}]", paramsData.FileIds.ToLog()) },
            };


            //Log transaction begin
            tranLog.LogBegin();


            string outputDirPath = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetTempFileName()));
            //string tempDirPath = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetTempFileName()));
            DataSet queryDataSet = new DataSet();


            using (SqlConnection con = new SqlConnection(WebApp.GetSystemConnectionString()))
            {
                con.Open();

                using (SqlCommand comm = new SqlCommand("IH_100020.WEB.RemoveDmtSourceFiles", con))
                {
                    comm.CommandType = CommandType.StoredProcedure;
                    comm.CommandTimeout = 300;

                    comm.Parameters.Add(new SqlParameter("@currentUser", SqlDbType.VarChar)).Value = WebApp.GetUserName();
                    comm.Parameters.Add(new SqlParameter("@ids", SqlDbType.VarChar)).Value = string.Join(";", paramsData.FileIds);

                    using (var da = new SqlDataAdapter(comm))
                    {
                        logger.DebugFormat("Calling procedure {0} ...", comm.CommandText);

                        da.Fill(queryDataSet);
                    }

                    //comm.ExecuteNonQuery();

                    ////DALSecurity.CallSecuredProcedure(con, comm);
                }
            }


            //Fetch source to check compilation
            var source = this.FetchScriptSource(paramsData.Id.Value);
            string code = source.Item4;


            //Build source
            var buildResponse = this.BuildSource(paramsData.Id.Value, code, "temp", outputDirPath, true);


            //Delete temp folder created for compilation output.
            this.ClearDirectory(outputDirPath);

            Directory.Delete(outputDirPath);


            //Set success response
            if (response == null)
                response = new Helpers.Common.Response(true, buildResponse.Message, queryDataSet.ToDictionary());


            //Log transaction end
            tranLog.LogEnd(response);
        }
        catch (Exception ex)
        {
            if (response == null)
                response = new SqlResponse(ex).ToResponse();

            if (tranLog != null)
            {
                //Log transaction end with error
                tranLog.LogEnd(ex);
            }
            else
            {
                this.logger.Error(ex);
            }
        }

        return new MemoryStream(Encoding.UTF8.GetBytes(this.jsSerializer.Serialize(response)));
    }
    public Stream SaveSource(Stream parameters)
    {
        Helpers.Common.Response response = null;
        TransactionLogger tranLog = null;

        try
        {
            //Deserialize parameters
            StreamReader sr = new StreamReader(parameters);
            var paramsData = this.jsSerializer.Deserialize<SaveSourceParameters>(sr.ReadToEnd());
            sr.Dispose();


            //Initialize log stuff.
            tranLog = new TransactionLogger(this.logger, MethodBase.GetCurrentMethod().Name);

            tranLog.ParametersCollection = new Dictionary<string, object>
            {
                { "Id", paramsData.Id },
                { "Code", paramsData.Code },
                { "Name", paramsData.Name },
                { "ScriptId", paramsData.ScriptId },
                { "Upload", paramsData.Upload },
            };


            //Log transaction begin
            tranLog.LogBegin();


            string outputDirPath = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetTempFileName()));
            byte[] package = null;
            DataSet sourceData = new DataSet();
            string tagNamesToRead = "";
            string tagNamesToWrite = "";
            Helpers.Common.Response buildResponse = null;


            //Put compilation in try/block because it is mandatory save the new code
            //to database no matter if code compile or not.
            try
            {
                //Build source
                buildResponse = this.BuildSource(
                    paramsData.Id.Value,
                    paramsData.Code,
                    paramsData.Name,
                    outputDirPath,
                    //Only fetch referenced files if script will not be uploaded.
                    ((paramsData.Upload.HasValue == false) || (paramsData.Upload.Value == false))
                );

                if (buildResponse.Success == true)
                {
                    if (paramsData.Upload == true)
                        package = this.BuildScriptPackage(outputDirPath);


                    //Delete temp folder created for compilation output.
                    this.ClearDirectory(outputDirPath);

                    Directory.Delete(outputDirPath);



                    //---------------------------------------
                    // Code parsing and validation
                    //---------------------------------------
                    var parseResults = Compiler.ParseCode(paramsData.Code);

                    if (parseResults.Success == true)
                    {
                        //Get name of all tags included in the code.
                        tagNamesToRead = string.Join("|", parseResults.ReadTagsNames);
                        tagNamesToWrite = string.Join("|", parseResults.WriteTagsNamesDigital)
                                    + "|" + string.Join("|", parseResults.WriteTagsNamesReal);
                    }
                    else
                    {
                        response = new Helpers.Common.Response(parseResults.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                this.logger.Error(ex);

                response = new SqlResponse(ex).ToResponse();
            }



            //Save code to database and send upload command if it is necessary.
            using (SqlConnection con = new SqlConnection(WebApp.GetSystemConnectionString()))
            {
                con.Open();

                using (SqlCommand comm = new SqlCommand("IH_100020.WEB.UpsertDmtSource", con))
                {
                    comm.CommandType = CommandType.StoredProcedure;
                    comm.CommandTimeout = 300;

                    comm.Parameters.Add(new SqlParameter("@id", SqlDbType.Int)).Value = paramsData.Id;
                    comm.Parameters.Add(new SqlParameter("@scriptId", SqlDbType.Int)).Value = paramsData.ScriptId;
                    comm.Parameters.Add(new SqlParameter("@code", SqlDbType.VarChar)).Value = paramsData.Code;
                    comm.Parameters.Add(new SqlParameter("@package", SqlDbType.VarBinary)).Value = package;
                    comm.Parameters.Add(new SqlParameter("@tagsNameToRead", SqlDbType.VarChar)).Value = tagNamesToRead;
                    comm.Parameters.Add(new SqlParameter("@tagsNameToWrite", SqlDbType.VarChar)).Value = tagNamesToWrite;
                    comm.Parameters.Add(new SqlParameter("@currentUser", SqlDbType.VarChar)).Value = WebApp.GetUserName();
                    comm.Parameters.Add(new SqlParameter("@returnData", SqlDbType.Bit)).Value = true;

                    using (SqlDataAdapter da = new SqlDataAdapter(comm))
                    {
                        this.logger.DebugFormat("Calling procedure {0} ...", comm.CommandText);

                        da.Fill(sourceData);

                        //comm.ExecuteNonQuery();

                        ////DALSecurity.CallSecuredProcedure(con, comm);
                    }
                }
            }


            //Set success response
            //Do not override response in case that compilation failed an already set the response.
            if (response == null)
                response = new Helpers.Common.Response(true, buildResponse.Message, sourceData.ToDictionary());


            //Log transaction end
            tranLog.LogEnd(response);
        }
        catch (Exception ex)
        {
            if (response == null)
                response = new SqlResponse(ex).ToResponse();

            if (tranLog != null)
            {
                //Log transaction end with error
                tranLog.LogEnd(ex);
            }
            else
            {
                this.logger.Error(ex);
            }
        }

        return new MemoryStream(Encoding.UTF8.GetBytes(this.jsSerializer.Serialize(response)));
    }
    public Stream UploadSourceFiles(Stream parameters)
    {
        Helpers.Common.Response response = null;
        TransactionLogger tranLog = null;

        try
        {
            //Deserialize parameters
            StreamReader sr = new StreamReader(parameters);
            var paramsData = this.jsSerializer.Deserialize<SourceFilesParameters>(sr.ReadToEnd());
            sr.Dispose();


            //Initialize log stuff.
            tranLog = new TransactionLogger(this.logger, MethodBase.GetCurrentMethod().Name);

            tranLog.ParametersCollection = new Dictionary<string, object>
            {
                { "Id", paramsData.Id },
                { "Files", string.Format("[{0}]", paramsData.FileNames.Select(item => {
                    int i = paramsData.FileNames.ToList().IndexOf(item);

                    return new
                    {
                        Name = item,
                        ContentLength = paramsData.Files[i].Length,
                    };
                }).ToLog()) },
            };


            //Log transaction begin
            tranLog.LogBegin();


            string outputDirPath = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetTempFileName()));
            //string tempDirPath = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetTempFileName()));
            DataTable filesDataTable = new DataTable();
            DataSet filesDataSet = new DataSet();


            filesDataTable.Columns.Add("Id", typeof(int));
            filesDataTable.Columns.Add("Name", typeof(string));
            filesDataTable.Columns.Add("Content", typeof(byte[]));


            for (int i = 0; i < paramsData.Files.GetLength(0);  i++)
            {
                byte[] fileContent = Convert.FromBase64String(paramsData.Files[i]);
                string fileName = paramsData.FileNames[i];

                //File.WriteAllBytes(Path.Combine(tempDirPath, fileName), fileContent);

                filesDataTable.Rows.Add(0, fileName, fileContent);
            }


            using (SqlConnection con = new SqlConnection(WebApp.GetSystemConnectionString()))
            {
                con.Open();

                using (SqlCommand comm = new SqlCommand("IH_100020.WEB.UpsertDmtSourceFiles", con))
                {
                    comm.CommandType = CommandType.StoredProcedure;
                    comm.CommandTimeout = 300;

                    comm.Parameters.Add(new SqlParameter("@currentUser", SqlDbType.VarChar)).Value = WebApp.GetUserName();
                    comm.Parameters.Add(new SqlParameter("@sourceId", SqlDbType.Int)).Value = paramsData.Id;

                    //Add files parameter
                    comm.Parameters.Add(
                        new SqlParameter("@files", SqlDbType.Structured)
                        {
                            TypeName = "DMT.[File]",
                            Value = filesDataTable
                        }
                    );


                    using (var da = new SqlDataAdapter(comm))
                    {
                        logger.DebugFormat("Calling procedure {0} ...", comm.CommandText);

                        da.Fill(filesDataSet);
                    }

                    //comm.ExecuteNonQuery();

                    ////DALSecurity.CallSecuredProcedure(con, comm);
                }
            }


            //Fetch source to check compilation
            var source = this.FetchScriptSource(paramsData.Id.Value);
            string code = source.Item4;


            //Build source
            var buildResponse = this.BuildSource(paramsData.Id.Value, code, "temp", outputDirPath, true);


            //Delete temp folder created for compilation output.
            this.ClearDirectory(outputDirPath);

            Directory.Delete(outputDirPath);


            //Set success response
            if (response == null)
                response = new Helpers.Common.Response(true, buildResponse.Message, filesDataSet.ToDictionary());


            //Log transaction end
            tranLog.LogEnd(response);
        }
        catch (Exception ex)
        {
            if (response == null)
                response = new SqlResponse(ex).ToResponse();

            if (tranLog != null)
            {
                //Log transaction end with error
                tranLog.LogEnd(ex);
            }
            else
            {
                this.logger.Error(ex);
            }
        }

        return new MemoryStream(Encoding.UTF8.GetBytes(this.jsSerializer.Serialize(response)));
    }

    #endregion

    #endregion

    #region Sub classes

    public class ScriptParameters
    {
        public int? Id;
        public string Name;

        public ScriptParameters() { }
    }
    public class SourceParameters : ScriptParameters
    {
        public string Code;
        public int? ScriptId;

        public SourceParameters() { }
    }
    public class SaveSourceParameters: SourceParameters
    {
        public bool? Upload;

        public SaveSourceParameters() { }
    }
    public class SourceFilesParameters : SourceParameters
    {
        public int[] FileIds;
        public string[] FileNames;
        public string[] Files;

        public SourceFilesParameters() { }
    }

    #endregion
}
