import objgraph
import sys
import weakref

from shiboken6 import Shiboken

from PySide6.QtCore import QTimer, QUrl, QLibraryInfo, QCoreApplication, QObject, Slot
from PySide6.QtWidgets import QApplication
from PySide6.QtNetwork import QNetworkRequest, QNetworkAccessManager


opt_verbose = False
opt_track_weakref = False
opt_track_destroy = False


def weakref_cb(r):
    print('WEAKREF_CB', r, '!')


class App(QObject):
    def __init__(self, url):
        super().__init__()
        self.url = url
        self.app = QApplication(sys.argv)
        self.timer = QTimer(self.app)
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self._tick)
        self.manager = QNetworkAccessManager(self.app)
        self.request = None
        self._n = 0
        self._weakrefs = []

    def run(self):
        self.timer.start()
        self.app.exec()

    @Slot()
    def _tick(self):
        global WEAK_REF
        print(f"\nTICK #{self._n}")
        if self.request is not None:
            return
        objgraph.show_growth()

        self.request = QNetworkRequest()
        self.request.setUrl(QUrl(self.url))
        self.request.setRawHeader(b"User-Agent", b"Test")
        reply = self.manager.get(self.request)
        on = f"reply{self._n}"
        reply.setObjectName(on)
        ref_cnt = sys.getrefcount(reply)
        print('>>>QNetworkAccessManager.get()', reply, "refs=", ref_cnt)
        if opt_verbose or self._n == 0:
            print(Shiboken.dump(reply))
        reply.finished.connect(self._finished)
        if opt_track_destroy:
            reply.destroyed.connect(self._reply_destroyed)
            print('destr')
        if opt_track_weakref:
            wr = weakref.ref(reply, weakref_cb)
            self._weakrefs.append(wr)
            print('created weak_ref', wr, f'for "{on}"')
        ref_cnt = sys.getrefcount(reply)  # Careful: Passing as func arg might falsify refcount
        print('<<<QNetworkAccessManager.get()', "refs=", ref_cnt, '\n')
        self._n += 1

    @Slot()
    def _finished(self):
        reply = self.sender()
        ref_cnt = sys.getrefcount(reply)
        print("\n>FINISHED", reply, "refs=", ref_cnt)
        reply.close()
        reply.finished.disconnect()
        reply.deleteLater()
        ref_cnt = sys.getrefcount(reply)
        print("<FINISHED", reply, "refs=", ref_cnt)
        self.request = None
        if self._n > 4:
            self.timer.stop()
            QCoreApplication.quit()

    @Slot(QObject)
    def _reply_destroyed(self, r):
        ref_cnt = sys.getrefcount(r)
        print('>>>QNetworkReply.destroyed()', r, "refs=", ref_cnt)
        if opt_verbose:
            print(Shiboken.dump(r))
        print('<<< QNetworkReply.destroyed()')


def main():
    global opt_verbose, opt_track_weakref, opt_track_destroy
    print('Python {}.{}.{}'.format(sys.version_info[0], sys.version_info[1],
                                   sys.version_info[2]))
    print(QLibraryInfo.build())
    opt_verbose = '-v' in sys.argv
    opt_track_weakref = '-w' in sys.argv
    opt_track_destroy = '-d' in sys.argv
    app_inst = App('http://www.google.com')
    app_inst.run()


if __name__ == '__main__':
    main()
