import objgraph
import sys
import weakref

from PyQt6.QtCore import QTimer, QUrl, QCoreApplication, QObject, pyqtSlot, qVersion
from PyQt6.QtWidgets import QApplication
from PyQt6.QtNetwork import QNetworkRequest, QNetworkAccessManager


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()

    @pyqtSlot()
    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, f'"{on}" refs={ref_cnt}')
        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()', f'"{on}" refs={ref_cnt}\n')
        self._n += 1

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

    @pyqtSlot(QObject)
    def _reply_destroyed(self, r):
        ref_cnt = sys.getrefcount(r)
        on = r.objectName()
        print('QNetworkReply.destroyed()', r, f'"{on}" refs={ref_cnt}')


def main():
    global opt_verbose, opt_track_weakref, opt_track_destroy
    print('PyQt Python {}.{}.{}'.format(sys.version_info[0], sys.version_info[1],
                                   sys.version_info[2]))
    print('PyQt ' + qVersion())
    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()
