import clr

from System.Environment import CurrentDirectory
from System.IO import Path, Directory

from System.CodeDom import Compiler
from Microsoft.CSharp import CSharpCodeProvider


def Generate(code, name, references=None, outputDirectory=None, inMemory=False):
    CompilerParams = Compiler.CompilerParameters()

    if outputDirectory is None:
        outputDirectory = Directory.GetCurrentDirectory()
    if not inMemory:
        CompilerParams.OutputAssembly = Path.Combine(outputDirectory, name + ".dll")
        CompilerParams.GenerateInMemory = False
    else:
        CompilerParams.GenerateInMemory = True

    CompilerParams.TreatWarningsAsErrors = False
    CompilerParams.GenerateExecutable = False
    CompilerParams.CompilerOptions = "/optimize"

    for reference in references or []:
        CompilerParams.ReferencedAssemblies.Add(reference)

    provider = CSharpCodeProvider()
    compile = provider.CompileAssemblyFromSource(CompilerParams, code)

    if compile.Errors.HasErrors:
        raise Exception("Compile error: %r" % list(compile.Errors.List))

    if inMemory:
        return compile.CompiledAssembly
    return compile.PathToAssembly

unmanaged_code = """
using System;
using System.Runtime.InteropServices;

namespace pyrar
{
public class unrar
{
    public const int ERAR_END_ARCHIVE = 10;
    public const int ERAR_NO_MEMORY = 11;
    public const int ERAR_BAD_DATA = 12;
    public const int ERAR_BAD_ARCHIVE = 13;
    public const int ERAR_UNKNOWN_FORMAT = 14;
    public const int ERAR_EOPEN = 15;
    public const int ERAR_ECREATE = 16;
    public const int ERAR_ECLOSE = 17;
    public const int ERAR_EREAD = 18;
    public const int ERAR_EWRITE = 19;
    public const int ERAR_SMALL_BUF = 20;

    public const int RAR_OM_LIST = 0;
    public const int RAR_OM_EXTRACT = 1;

    public const int RAR_SKIP = 0;
    public const int RAR_TEST = 1;
    public const int RAR_EXTRACT = 2;

    public const int RAR_VOL_ASK = 0;
    public const int RAR_VOL_NOTIFY = 1;

    public enum RarOperations
    {
    OP_EXTRACT = 0,
    OP_TEST = 1,
    OP_LIST = 2
    }

    public struct RARHeaderData
    {
    public string ArcName;
    public string FileName;
    public uint Flags;
    public uint PackSize;
    public uint UnpSize;
    public uint HostOS;
    public uint FileCRC;
    public uint FileTime;
    public uint UnpVer;
    public uint Method;
    public uint FileAttr;
    public string CmtBuf;
    public uint CmtBufSize;
    public uint CmtSize;
    public uint CmtState;
    }

    public struct RAROpenArchiveData
    {
    public string ArcName;
    public uint OpenMode;
    public uint OpenResult;
    public string CmtBuf;
    public uint CmtBufSize;
    public uint CmtSize;
    public uint CmtState;
    }

    public struct RAROpenArchiveDataEx
    {
    public string ArcName;
    public string ArcNameW;
    public uint OpenMode;
    public uint OpenResult;
    public string CmtBuf;
    public uint CmtBufSize;
    public uint CmtSize;
    public uint CmtState;
    public uint Flags;
    public uint Reserved;
    }
    public struct RARHeaderDataEx
    {
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public string ArcName;

    public string ArcNameW;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public string FileName;

    public string FileNameW;
    public uint Flags;
    public uint PackSize;
    public uint PackSizeHigh;
    public uint UnpSize;
    public uint UnpSizeHigh;
    public uint HostOS;
    public uint FileCRC;
    public uint FileTime;
    public uint UnpVer;
    public uint Method;
    public uint FileAttr;
    public string CmtBuf;
    public uint CmtBufSize;
    public uint CmtSize;
    public uint CmtState;
    public uint Reserved;
    };


    [DllImportAttribute("unrar.dll")]
    public static extern IntPtr RAROpenArchive (ref
    RAROpenArchiveData ArchiveData);
    [DllImportAttribute("unrar.dll")]
    public static extern int RARCloseArchive(IntPtr hArcData);
    [DllImportAttribute("unrar.dll")]
    public static extern int RARReadHeader (IntPtr hArcData, ref
    RARHeaderData HeaderData);
    [DllImportAttribute("unrar.dll")]
    public static extern IntPtr RAROpenArchiveEx(ref
    RAROpenArchiveDataEx ArchiveData);
    [DllImportAttribute("unrar.dll")]
    public static extern int RARReadHeaderEx(IntPtr hArcData, ref
    RARHeaderDataEx HeaderData);
    [DllImportAttribute("unrar.dll")]
    public static extern int RARProcessFile(IntPtr hArcData, int
    Operation, string DestPath, string DestName);
    [DllImportAttribute("unrar.dll")]
    public static extern int RARGetDllVersion();
    [DllImportAttribute("unrar.dll")]
    public static extern int RARSetPassword(IntPtr hArcData,string
    Password);
}
}
"""

assembly = Generate(unmanaged_code, 'pyrar.dll', inMemory=False)
