module M

include("CodeGen.jl")
using .CodeGen: PType, Struct, Field, Method, GlobalMethod, operator
using .CodeGen: @field, @type, write_cpp_typestub, write_jl_typestub, write_cpp_methodstub

const CPP_DIR = abspath(joinpath(@__DIR__, "../ibapi-wrapper/include/generated"))
const JL_DIR = abspath(joinpath(@__DIR__, "../src/IBKR/IBKRCore/generated"))
@assert isdir(abspath(joinpath(CPP_DIR, "..")))
@assert isdir(abspath(joinpath(JL_DIR, "..")))

const MOD = :mod

rm(CPP_DIR; recursive=true, force=true)
rm(JL_DIR; recursive=true, force=true)
mkdir(CPP_DIR)
mkdir(JL_DIR)

jlfile(t::Struct) = "$(t.name).jl"
cppfile(t::Struct) = "$(t.name).h"
function write_stub(type::Struct, methods::Vector{GlobalMethod} = GlobalMethod[];  extra_cpp_typestub = [], extra_cpp_methodstub = [])
    write_jl_typestub(joinpath(JL_DIR, "$(type.name).jl"), type)
    open(joinpath(CPP_DIR, "$(type.name).h"), "w") do io
        write_cpp_typestub(io, MOD, type, extra=extra_cpp_typestub)
        write_cpp_methodstub(io, MOD, methods, extra=extra_cpp_methodstub)
    end
end

let T = Struct(
        :ComboLeg;
        fields=[
            Field(:conId, :CxxLong),
            Field(:ratio, :CxxLong),
            Field(:action, :StdString),
            Field(:exchange, :StdString),
            Field(:openClose, :CxxLong),
            Field(:shortSaleSlot, :CxxLong),
            Field(:designatedLocation, :StdString),
            Field(:exemptCode, :CxxLong),
        ],
    )
    write_stub(T, [
        operator(:(==), T),
        GlobalMethod(:ComboLegSPtr, "[]() { return ComboLegSPtr(new ComboLeg); }"),
        GlobalMethod(:showComboLeg, "&showComboLeg"),
        ],
        extra_cpp_methodstub = [
            "jlcxx::stl::apply_stl<ComboLeg>(mod)"
        ],
    )
end

let T = Struct(
        :Contract;
        fields=[
            Field(:conId, :CxxLong),
            Field(:symbol, :StdString), 
            Field(:secType, :StdString), 
            Field(:lastTradeDateOrContractMonth, :StdString), 
            Field(:strike, :Cdouble), 
            Field(:right, :StdString), 
            Field(:multiplier, :StdString), 
            Field(:exchange, :StdString), 
            Field(:primaryExchange, :StdString), 
            Field(:currency, :StdString), 
            Field(:localSymbol, :StdString), 
            Field(:tradingClass, :StdString), 
            Field(:includeExpired, :CxxBool), 
            Field(:secIdType, :StdString), 
            Field(:secId, :StdString), 

            Field(:comboLegsDescrip, :StdString),
            Field(:comboLegs, PType(:SharedPtr, PType(:StdVector, PType(:SharedPtr, :ComboLeg))), mutable=false),
            # Field(:comboLegs, PType(:StdVector, PType(:SharedPtr, :ComboLeg))),
        ],
    )
    write_stub(T) 
end

end
