# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'Screenshot_GUI.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


import shutil
import sys
from datetime import datetime
from pathlib import Path

from PIL import ImageGrab
from PyQt5.QtCore import QRect, Qt, QPoint, QMetaObject, QThread
from PyQt5.QtGui import QIcon, QFont, QColor, QImage, QPixmap, QPen, QPainter
from PyQt5.QtWidgets import (QMainWindow, QApplication, QDesktopWidget, QWidget, QFrame,
                             QLabel, QPushButton, QComboBox, QCheckBox, QSpinBox, QDialog, QFileDialog, QMessageBox)
from py7zr import pack_7zarchive, unpack_7zarchive

from Screenshot.Audio_record import AudioRecord
from Screenshot.Screenshot_record import Screenshot, file_path


def unpack_7zip_to_exe(filename):
    file_basename = Path(file_path(f'{filename}.exe'))
    if file_basename.exists():
        return True
    elif file_basename.with_suffix('.7z').exists():
        shutil.unpack_archive(file_basename.with_suffix('.7z'), file_basename.parent)
        return unpack_7zip_to_exe(file_basename.stem)
    else:
        return False

class Thread_screenshot(QThread):

    def __init__(self):
        super().__init__()
        self.offset_x = 0
        self.offset_y = 0
        self.draw_mouse = 1
        self.filename = ''
        self.screen = Screenshot()

    def config_modify(self, **kwargs):
        self.screen.width = kwargs.get('width', self.screen.width)
        self.screen.height = kwargs.get('height', self.screen.height)
        self.screen.fps = kwargs.get('fps', self.screen.fps)
        self.offset_x = kwargs.get('offset_x', self.offset_x)
        self.offset_y = kwargs.get('offset_y', self.offset_y)
        self.draw_mouse = kwargs.get('draw_mouse', self.draw_mouse)
        self.filename = kwargs.get('filename', self.filename)

    def compose(self):
        video = self.filename + '.mp4'
        audio = self.filename + '.mp3'
        self.screen.compose_audio(video, audio, video.replace('缓存', ''))
        QThread.sleep(1)
        self.stop()
        Path(audio).unlink()
        Path(video).unlink()

    def run(self):
        if not self.filename:
            raise Exception('请输入filename!')
        filename = self.filename + '.mp4'
        self.screen.record(filename, self.offset_x, self.offset_y, self.draw_mouse)

    def stop(self):
        self.screen.terminate()


class Ui_MainWindow1(QMainWindow):
    """主体窗口设置"""

    def __init__(self):
        super().__init__()
        self.setObjectName("MainWindow")
        self.setWindowTitle('屏幕录制')
        windowico = file_path('gui_svg.svg')
        self.setWindowIcon(QIcon(windowico))
        self.resize(512, 352)
        self.setFixedSize(512, 352)
        self._dir = '.'
        self.fname = ''
        self.offset_x, self.offset_y = 0, 0
        self.screen_x, self.screen_y = ImageGrab.grab().size
        self.audio = AudioRecord()
        self.audio.get_in_out_devices()
        self.device_name = None
        self.record_audio = True if self.audio.input_dict else False
        self.hotkey_start = False
        self.screenshot = Thread_screenshot()
        self.setupUi()
        ffmpeg_exists = unpack_7zip_to_exe('ffmpeg')
        if not ffmpeg_exists:
            QMessageBox.warning(self, '请下载ffmpeg！', '请将ffmpeg.exe放在resource目录下再录制！')
        self.show()

    def setupUi(self):
        self.centralwidget = QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.label0 = QLabel(self.centralwidget)
        self.label0.setGeometry(QRect(0, 0, 421, 351))
        self.label0.setObjectName("scrollArea")
        # 添加边框
        self.label0.setFrameShape(QFrame.Box)
        self.label0.setFrameShadow(QFrame.Sunken)
        self.get_screen_grab((0, 0, self.screen_x, self.screen_y))
        self.label0.setAlignment(Qt.AlignCenter)
        self.label_1 = QLabel(self.centralwidget)
        font = QFont()
        font.setBold(True)
        self.label_1.setGeometry(QRect(430, 0, 85, 31))
        self.label_1.setTextFormat(Qt.AutoText)
        self.label_1.setFont(font)
        self.label_1.setScaledContents(True)
        self.label_1.setObjectName("屏幕录制器")
        self.label_6 = QLabel(self.centralwidget)
        self.label_6.setGeometry(QRect(430, 20, 85, 31))
        self.label_6.setTextFormat(Qt.AutoText)
        self.label_6.setScaledContents(True)
        self.label_6.setObjectName("注释1")
        self.checkbox = QCheckBox(self.centralwidget)
        self.checkbox.setGeometry(QRect(430, 100, 85, 20))
        self.checkbox.setChecked(True)
        self.checkbox.stateChanged.connect(self.mouse_draw)
        self.checkbox.setObjectName("录制鼠标")
        self.comboBox = QComboBox(self.centralwidget)
        self.comboBox.setGeometry(QRect(430, 200, 85, 20))
        self.comboBox.setEditable(False)
        self.comboBox.addItems(self.audio.input_dict.keys())
        self.comboBox.addItems(['无'])
        self.comboBox.setMaxVisibleItems(9)
        self.comboBox.currentTextChanged.connect(self.change_combox)
        self.comboBox.setObjectName("音频来源")
        self.comboBox_3 = QComboBox(self.centralwidget)
        self.comboBox_3.setGeometry(QRect(430, 260, 80, 20))
        self.comboBox_3.addItems(['双声道', '单声道'])
        self.comboBox_3.currentIndexChanged.connect(self.change_combox)
        self.comboBox_3.setObjectName("声道设置")
        self.pushButton = QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QRect(470, 320, 41, 31))
        self.pushButton.clicked.connect(self.stop)
        self.pushButton.setObjectName("停止")
        self.pushButton_2 = QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QRect(430, 320, 41, 31))
        self.pushButton_2.setObjectName("开始")
        self.pushButton_2.clicked.connect(self.start)
        self.pushButton_3 = QPushButton(self.centralwidget)
        self.pushButton_3.setGeometry(QRect(430, 290, 80, 23))
        self.pushButton_3.setObjectName("保存目录")
        self.pushButton_3.clicked.connect(self.open_dirpath)
        self.pushButton_4 = QPushButton(self.centralwidget)
        self.pushButton_4.setGeometry(QRect(430, 70, 80, 23))
        self.pushButton_4.setCheckable(True)
        self.pushButton_4.setObjectName("Size")
        self.pushButton_4.clicked.connect(self.get_screen_area)
        self.spinBox = QSpinBox(self.centralwidget)
        self.spinBox.setValue(15)
        self.spinBox.setRange(10, 60)
        self.spinBox.setGeometry(QRect(430, 145, 80, 20))
        self.spinBox.valueChanged.connect(self.screen_fps_mofify)
        self.spinBox.setObjectName("spinBox")
        self.label_2 = QLabel(self.centralwidget)
        self.label_2.setGeometry(QRect(430, 50, 54, 16))
        self.label_2.setTextFormat(Qt.AutoText)
        self.label_2.setObjectName("选择区域")
        self.label_3 = QLabel(self.centralwidget)
        self.label_3.setGeometry(QRect(430, 125, 54, 16))
        self.label_3.setObjectName("帧率")
        self.label_4 = QLabel(self.centralwidget)
        self.label_4.setGeometry(QRect(430, 240, 54, 16))
        self.label_4.setObjectName("声道设置")
        self.label_5 = QLabel(self.centralwidget)
        self.label_5.setGeometry(QRect(430, 180, 54, 16))
        self.label_5.setObjectName("音频来源")
        self.setCentralWidget(self.centralwidget)

        self.retranslateUi()
        QMetaObject.connectSlotsByName(self)

    def retranslateUi(self):
        self.pushButton.setText("停止")
        self.pushButton_2.setText("开始")
        self.pushButton_3.setText("保存目录")
        self.pushButton_4.setText("Size*Size")
        self.checkbox.setText("录制鼠标")
        self.label_1.setText("屏幕录制器")
        self.label_2.setText("选择区域：")
        self.label_3.setText("帧率：")
        self.label_4.setText("声道设置：")
        self.label_5.setText("音频来源：")
        self.label_6.setText("F7：开始/停止")

    def keyPressEvent(self, event):
        """监测键盘是否按下F3，如果已开始录制则停止，否则开始录制"""
        if event.key() == Qt.Key_F7:
            if not self.hotkey_start:
                self.start()
            else:
                self.stop()

    def change_combox(self, event):
        sendername = self.sender().objectName()
        if sendername == '声道设置':
            self.channels = 2 if event == 0 else 1
        elif sendername == '音频来源':
            if event == '无':
                self.record_audio = False
            else:
                self.record_audio = True
                self.device_name = event

    def get_screen_grab(self, crop_size):
        # 获取屏幕截图并更新至self.label0中
        screen = ImageGrab.grab().convert('RGBA')
        screen = screen.crop(box=crop_size)  # box=(left, upper, right, lower)
        data = screen.tobytes("raw", "RGBA")
        qim = QImage(data, screen.size[0], screen.size[1], QImage.Format_RGBA8888)
        pix = QPixmap.fromImage(qim).scaled(self.label0.size(), aspectRatioMode=Qt.KeepAspectRatio)
        pix.detach()  # QPixmap为另开线程操作的，避免程序崩溃，使用detach方法使用一个QImage对象直到QPixmap对象销毁
        self.label0.setPixmap(pix)
        self.label0.repaint()
        return screen.size

    def get_screen_area(self):
        # 获取截图区间
        SizeScreen = MousePaint()
        SizeScreen.exec_()
        self.offset_x, self.offset_y = SizeScreen.lastpoint
        end_x, end_y = SizeScreen.endpoint
        self.screen_x, self.screen_y = self.get_screen_grab((self.offset_x, self.offset_y, end_x, end_y))
        self.screenshot.config_modify(offset_x=self.offset_x, offset_y=self.offset_y,
                                      width=self.screen_x, height=self.screen_y)
        self.pushButton_4.setText(f'{self.screen_x}*{self.screen_y}')

    def screen_fps_mofify(self, fps):
        self.screenshot.config_modify(fps=fps)

    def mouse_draw(self, checked):
        draw_mouse = 1 if checked else 0
        self.screenshot.config_modify(draw_mouse=draw_mouse)

    def open_dirpath(self):
        fdir = QFileDialog.getExistingDirectory(self, '选择目录', self._dir)
        if not fdir:
            return None
        self._dir = fdir
        self.set_filename()

    def set_filename(self):
        self.fname = f'{self._dir}/屏幕录制缓存_{int(datetime.now().replace(microsecond=0).timestamp())}'
        self.screenshot.config_modify(filename=self.fname)
        self.audio = AudioRecord()
        self.setWindowTitle(f'屏幕录制 {self.fname}')

    def start(self):
        if self.hotkey_start:
            return
        if not self.fname:
            QMessageBox.warning(self, '请选择保存目录！', '请选择保存目录！')
            return
        self.screenshot.start()
        if self.record_audio:
            self.audio.stop_flag = False
            self.audio.run(filename=self.fname + '.mp3', name=self.device_name)
        self.hotkey_start = True

    def stop(self):
        if not self.hotkey_start:
            return
        self.audio.stop_flag = True
        self.hotkey_start = False
        self.screenshot.stop()
        if self.record_audio:
            self.screenshot.compose()
        else:
            filename = self.fname + '.mp4'
            target = filename.replace('缓存', '')
            Path(filename).replace(target)
        self.set_filename()


class MousePaint(QDialog):
    """移动鼠标获取屏幕捕获范围"""

    def __init__(self):
        super().__init__()
        self.setMouseTracking(True)
        # 设置窗口布满整个屏幕
        self.showFullScreen()
        # 设置窗体无边框
        self.setWindowFlags(Qt.FramelessWindowHint)  # 窗口置顶，无边框
        # 设置背景透明
        self.setWindowOpacity(0.5)
        self.initUI()
        self.setFocus()

    def initUI(self):
        self.setGeometry(*(QDesktopWidget().screenGeometry()).getRect())
        self.pix = QPixmap()
        self.lastpoint = QPoint()
        self.endpoint = QPoint()
        self.pos = None
        self.bline = 0

    def mousePressEvent(self, event):
        # 监听鼠标按压事件
        if event.button() == Qt.LeftButton:
            self.lastpoint = event.x(), event.y()
            self.bline = 1
        elif event.button() == Qt.RightButton:
            self.close()
        event.accept()

    def mouseReleaseEvent(self, event):
        # 监听鼠标释放事件
        self.endpoint = event.x(), event.y()
        self.bline = 0
        event.accept()
        self.close()

    def mouseMoveEvent(self, event):
        # 监听鼠标移动事件
        if self.bline == 1:
            self.pos = event.x(), event.y()
            event.accept()
            self.update()

    def paintEvent(self, event):
        # 绘画事件
        if self.bline == 1:
            pp = QPainter(self)
            pen = QPen()  # 定义笔格式对象
            pen.setWidth(5)  # 设置笔的宽度
            pen.setColor(QColor(255, 0, 0))
            pp.setPen(pen)
            lpx, lpy = self.lastpoint
            pp.drawRect(lpx, lpy, self.pos[0] - lpx, self.pos[1] - lpy)
            event.accept()


# def main():
#     """运行函数"""
#     # 将7zip压缩格式添加到shutil中
#     shutil.register_archive_format('7zip', pack_7zarchive, description='7zip archive')
#     shutil.register_unpack_format('7zip', ['.7z'], unpack_7zarchive, description='7zip archive')
#     app = QApplication(sys.argv)
#     app.setAttribute(Qt.AA_UseHighDpiPixmaps)
#     ui = Ui_MainWindow1()
#     sys.exit(app.exec_())


#if __name__ == '__main__':
#    main()
