import objc
from PyObjCTools.TestSupport import TestCase

NSObject = objc.lookUpClass("NSObject")
# _NSZombie = objc.lookUpClass('_NSZombie')
NSProxy = objc.lookUpClass("NSProxy")


class MethodAccessTest(TestCase):
    def testObjCObject(self):
        # Trying to access the methods of objc.objc_object should not
        # crash the interpreter.
        with self.assertRaisesRegex(
            AttributeError, "<nil> doesn't have attribute func_code"
        ):
            objc.objc_object.pyobjc_classMethods.func_code

        with self.assertRaisesRegex(
            AttributeError, "<nil> doesn't have attribute func_code"
        ):
            objc.objc_object.pyobjc_instanceMethods.func_code,

    def testNSProxyStuff(self):
        # NSProxy is incompatitble with pyobjc_{class,instance}Methods, but
        # this should not crash the interpreter
        with self.assertRaisesRegex(AttributeError, "No selector foobar"):
            NSProxy.pyobjc_instanceMethods.foobar

        with self.assertRaisesRegex(AttributeError, "No selector foobar"):
            NSProxy.pyobjc_classMethods.foobar

        with self.assertRaisesRegex(AttributeError, "No attribute foobar"):
            NSProxy.foobar

    def testDir(self):
        o = NSObject.new()

        d = dir(o.pyobjc_instanceMethods)
        self.assertGreater(len(d), 10)
        self.assertIn("init", d)

        d = dir(NSObject.pyobjc_classMethods)
        self.assertGreater(len(d), 10)
        self.assertIn("alloc", d)

    def testDict(self):
        o = NSObject.new()

        d = o.pyobjc_instanceMethods.__dict__.keys()
        self.assertGreater(len(d), 10)
        self.assertIn("init", d)

        d = NSObject.pyobjc_classMethods.__dict__.keys()
        self.assertGreater(len(d), 10)
        self.assertIn("alloc", d)

        # d = o.pyobjc_classMethods.__dict__.keys()
        # self.assertGreater(len(d), 10)
        # self.assertIn("alloc", d)

    def testAttributes(self):
        o = NSObject.new()

        self.assertHasAttr(o.pyobjc_instanceMethods, "init")
        # self.assertHasAttr(o.pyobjc_classMethods, "alloc")

        self.assertHasAttr(NSObject.pyobjc_classMethods, "alloc")


class ClassAndInstanceMethods(TestCase):
    def testClassThroughInstance(self):
        # Class methods are not accessible through instances.
        with self.assertRaisesRegex(
            AttributeError, "'NSObject' object has no attribute 'alloc'"
        ):
            NSObject.new().alloc
