#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2018 GoPro Inc.
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

from fractions import Fraction
from PySide2 import QtCore, QtGui, QtWidgets


class Seekbar(QtWidgets.QWidget):

    play = QtCore.Signal()
    pause = QtCore.Signal()
    seek = QtCore.Signal(float)
    step = QtCore.Signal(int)
    stop = QtCore.Signal()

    SLIDER_TIMEBASE = 1000
    SLIDER_TIMESCALE = 1. / SLIDER_TIMEBASE

    def __init__(self, config, stop_button=True):
        super(Seekbar, self).__init__()

        self._slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self._time_lbl = QtWidgets.QLabel()
        self._time_lbl.setFont(QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont))

        stop_btn = QtWidgets.QToolButton()
        stop_btn.setText(u'■')
        self._action_btn = QtWidgets.QToolButton()
        self._action_btn.setText(u'▶')
        self._action_btn.setCheckable(True)

        fw_btn = QtWidgets.QToolButton()
        fw_btn.setText('>')
        bw_btn = QtWidgets.QToolButton()
        bw_btn.setText('<')

        layout = QtWidgets.QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        if stop_button:
            layout.addWidget(stop_btn)
        layout.addWidget(bw_btn)
        layout.addWidget(self._action_btn)
        layout.addWidget(fw_btn)
        layout.addWidget(self._slider)
        layout.addWidget(self._time_lbl)

        self._frame_index = 0
        self._scene_duration = 0
        self._framerate = Fraction(*config.get('framerate'))
        self._set_action('pause')

        self._slider.sliderMoved.connect(self._slider_moved)
        self._slider.sliderPressed.connect(self._slider_pressed)
        self._slider.sliderReleased.connect(self._slider_released)
        self._slider_dragged = False

        stop_btn.clicked.connect(self._stop)
        self._action_btn.clicked.connect(self._toggle_playback)
        fw_btn.clicked.connect(self._step_fw)
        bw_btn.clicked.connect(self._step_bw)

    def _set_action(self, action):
        if action == 'play':
            self._action_btn.setChecked(True)
        elif action == 'pause':
            self._action_btn.setChecked(False)
        self._current_state = action

    @QtCore.Slot(int)
    def _slider_moved(self, value):  # only user move
        if not self._scene_duration:
            return
        self.seek.emit(value * self.SLIDER_TIMESCALE)

    @QtCore.Slot()
    def _slider_pressed(self):
        self._slider_dragged = True

    @QtCore.Slot()
    def _slider_released(self):
        self._slider_dragged = False
        self._refresh()

    @QtCore.Slot()
    def _toggle_playback(self):
        if self._current_state == 'play':
            self.pause.emit()
        else:
            self.play.emit()

    @QtCore.Slot()
    def _stop(self):
        self._set_action('pause')
        self.stop.emit()

    @QtCore.Slot()
    def _step_fw(self):
        self.step.emit(1)

    @QtCore.Slot()
    def _step_bw(self):
        self.step.emit(-1)

    def _get_time_lbl_text(self, frame_index, frame_time):
        cur_time = '%02d:%02d' % divmod(frame_time, 60)
        duration = '%02d:%02d' % divmod(self._scene_duration, 60)
        return '%s / %s (%d @ %.4gHz)' % (cur_time, duration, frame_index, self._framerate)

    @QtCore.Slot(dict)
    def set_scene_metadata(self, cfg):
        self._scene_duration = cfg['duration']
        self._framerate = Fraction(*cfg['framerate'])
        self._slider.setRange(0, self._scene_duration * self.SLIDER_TIMEBASE)
        self._refresh()

    @QtCore.Slot(int, float)
    def set_frame_time(self, frame_index, frame_time):
        self._frame_index = frame_index
        self._refresh()

    @QtCore.Slot()
    def set_play_state(self):
        self._set_action('play')

    @QtCore.Slot()
    def set_pause_state(self):
        self._set_action('pause')

    def _refresh(self):
        t = self._frame_index / self._framerate
        text = self._get_time_lbl_text(self._frame_index, t)
        self._time_lbl.setText(text)
        if not self._slider_dragged:
            self._slider.setValue(int(t * self.SLIDER_TIMEBASE))

@@ -859,16 +859,28 @@
 nse.%0A#%0A%0A
+import math%0A
 from fra
@@ -4070,24 +4070,637 @@
 framerate)%0A%0A
+    def _adjust_time_label_size(self):%0A        # Make the time label flexible again%0A        self._time_lbl.setMinimumSize(0, 0)%0A        self._time_lbl.setMaximumSize(0xffffff, 0xffffff)%0A%0A        # Set the label to its largest possible content (last frame)%0A        last_frame_index = int(math.ceil(self._scene_duration * self._framerate))%0A        text = self._get_time_lbl_text(last_frame_index, self._scene_duration)%0A        self._time_lbl.setText(text)%0A%0A        # Probe the occupied size and make it fixed for the current scene%0A        hint = self._time_lbl.sizeHint()%0A        self._time_lbl.setFixedSize(hint)%0A%0A
     @QtCore.
@@ -4928,16 +4928,55 @@
 MEBASE)%0A
+        self._adjust_time_label_size()%0A
         

force a fixed size for the time label