#!/usr/bin/python3

import ROOT
import cppyy


code = '''
struct Base {
    Base() {};

    const std::string& operator[](const std::string& x) {
        return x;
    };

    const std::string& operator()(const std::string& x) {
        return x;
    };

    int operator()(int x) {
        return x;
    };

};

struct Problematic: public Base {
    Problematic(): Base{} {};

    using Base::operator[];
    double operator()(double x) {
        return x+1;
    };

};

struct Good: public Base {
    Good(): Base{} {};

    using Base::operator[];
};
'''

def main():
    ROOT.gInterpreter.Declare(code)
    
    problem = cppyy.gbl.Problematic()
    good = cppyy.gbl.Good()

    try:
        # ROOT 6.22/00 -- modern PyROOT -- will fail
        # ROOT 6.22/00 -- legacy PyROOT -- will fail
        # ROOT 6.20/04 -- legacy PyROOT -- will fail
        print("Trying to call Problematic::operator()(const std::string&):")
        _ = problem('Call succeeded')
        print(_, '\n')
    except TypeError:
        print("Call to Problematic::operator()(const std::string&) failed\n")

    try:
        # ROOT 6.22/00 -- modern PyROOT -- will fail
        # ROOT 6.22/00 -- legacy PyROOT -- will succeed 
        # ROOT 6.20/04 -- legacy PyROOT -- will succeed 
        print("Trying to call Problematic::operator[](const std::string&):")
        _ = problem['Call succeeded']
        print(_, '\n')
    except TypeError:
        print("Call to Problematic::operator[](const std::string&) failed\n")
    
    try:
        # ROOT 6.22/00 -- modern PyROOT -- will select double overload 
        # ROOT 6.22/00 -- legacy PyROOT -- will select double overload 
        # ROOT 6.20/04 -- legacy PyROOT -- will select double overload 
        print("Trying to call Problematic::operator()(int):")
        inp = int(1)
        _ = problem(inp)
        if inp != _:
            print("Called Problematic::operator()(double)\n")
        else:
            print("Call succeeded")
    except TypeError:
        print("Call to Problematic::operator()(int) failed\n")

    try:
        # ROOT 6.22/00 -- modern PyROOT -- will succeed 
        # ROOT 6.22/00 -- legacy PyROOT -- will succeed 
        # ROOT 6.20/04 -- legacy PyROOT -- will succeed 
        print("Trying to call Good::operator[](const std::string&):")
        _ = good['Call succeeded']
        print(_, '\n')
    except TypeError:
        print("Call to Good::operator[](const std::string&) failed\n")

    try:
        # ROOT 6.22/00 -- modern PyROOT -- will succeed 
        # ROOT 6.22/00 -- legacy PyROOT -- will succeed 
        # ROOT 6.20/04 -- legacy PyROOT -- will succeed 
        print("Trying to call Good::operator[](const std::string&):")
        _ = good['Call succeeded']
        print(_, '\n')
    except TypeError:
        print("Call to Good::operator[](const std::string&) failed\n")


if __name__ == "__main__":
    main()
