class DownloadPopup(Toplevel):
    def __init__(self, master, info: dict, message_store: MessageStore, video_id: str = None):
        Toplevel.__init__(self, master)
        self.bind('<Escape>', lambda _: self.cancel())
        self.bind('<Return>', lambda _: self.ok())
        self.title('Get VOD')
        self.transient(master)
        self.grab_set()

        self.info: dict = info
        self.message_store: MessageStore = message_store
        self.chat_downloader: ChatDownloader = None

        self.updated_info: bool = False
        self.status_var = StringVar(value='...')
        self.content = Frame(self)
        self.content.pack(padx=20, pady=15)
        self.video_title_var = StringVar(value='')
        self.download_info_var = StringVar(value='')
        self.eta_var = StringVar(value='')
        Label(self.content, text='Enter a VOD URL or video ID:').pack(side=TOP, anchor=W, pady=(0, 5))
        self.entry = Entry(self.content, width=50)
        self.entry.pack(side=TOP, padx=2, pady=(0, 5))
        Label(self.content, textvariable=self.status_var).pack(side=TOP, anchor=W, pady=(0, 5))

        self.progress_var = IntVar(value=0)
        self.progress = Progressbar(self.content, variable=self.progress_var, maximum=1)
        self.progress.pack(side=TOP, fill=X, padx=2)

        Label(self.content, textvariable=self.video_title_var).pack(side=TOP, anchor=W, pady=(0, 5))
        Label(self.content, textvariable=self.download_info_var).pack(side=TOP, anchor=W, pady=(0, 5))
        Label(self.content, textvariable=self.eta_var).pack(side=TOP, anchor=W, pady=(0, 5))

        self.overwrite_cache_var = BooleanVar(value=False)
        self.overwrite_cache_check = Checkbutton(self.content, text='Overwrite cache',
                                                 variable=self.overwrite_cache_var)
        self.overwrite_cache_check.pack(side=TOP, anchor=W, pady=(0, 5))

        self.button = Button(self.content, text='OK', command=self.ok)
        self.button.pack(side=TOP)
        self.update()
        x_coord = self.master.winfo_x() + (self.master.winfo_width() // 2) - (self.winfo_width() // 2)
        y_coord = self.master.winfo_y() + (self.master.winfo_height() // 2) - (self.winfo_height() // 2)
        self.geometry(f'{self.winfo_width()}x{self.winfo_height()}+{x_coord}+{y_coord}')
        self.entry.focus_set()
        self.protocol('WM_DELETE_WINDOW', self.cancel)

        if video_id:
            self.entry.insert(0, video_id)
            self.overwrite_cache_check.focus_set()

            chat_filename: str = os.path.join(CACHE_FOLDER, f'chat-{video_id}.json')
            if not os.path.exists(chat_filename):
                self.ok()

    def cancel(self):
        if self.chat_downloader:
            self.chat_downloader.kill()
        self.info.clear()
        self.info.update({'title': 'Chat Player'})
        self.destroy()

    def ok(self):
        self.button.config(state=DISABLED)
        self.overwrite_cache_check.config(state=DISABLED)
        self.status_var.set('Validating...')
        self.after(1, self.validate)

    def validate(self):
        video_id: str = self.entry.get()
        if 'http' in video_id or 'twitch.tv' in video_id:
            video_id = parse_url(video_id)
        if len(video_id) > 0 and video_exists(video_id):
            self.chat_downloader = ChatDownloader(video_id, overwrite_cache=self.overwrite_cache_var.get())
            self.chat_downloader.start()
            self.after(1, self.download)
        else:
            self.status_var.set('Error: Invalid URL or video ID.')
            self.button.config(state=NORMAL)

    def download(self):
        if not self.chat_downloader.info:
            self.status_var.set('Getting info')
            self.after(100, self.download)
        elif not self.chat_downloader.messages:
            if not self.updated_info:
                self.status_var.set('Downloading chat')
                self.info.update(self.chat_downloader.info)
                self.video_title_var.set(self.info.get('title'))
                self.updated_info = True
            self.progress_var.set(self.chat_downloader.progress)
            self.download_info_var.set(
                f'{self.chat_downloader.num_messages} messages downloaded. '
                f'Duration {self.chat_downloader.duration_done_str}/{self.chat_downloader.duration_str}.')
            self.eta_var.set(f'ETA: {self.chat_downloader.eta_str}')
            self.after(100, self.download)
        else:
            self.message_store.set_messages(self.chat_downloader.messages)
            self.destroy()